{"id":21071282,"url":"https://github.com/yisuschrist/codecrafters-shell-rust","last_synced_at":"2025-10-19T09:06:00.578Z","repository":{"id":245470593,"uuid":"818346719","full_name":"YisusChrist/codecrafters-shell-rust","owner":"YisusChrist","description":"Welcome to the Build your own Shell challenge!","archived":false,"fork":false,"pushed_at":"2024-06-21T16:39:15.000Z","size":32,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-20T21:58:05.774Z","etag":null,"topics":["codecrafters","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/YisusChrist.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-21T16:37:14.000Z","updated_at":"2024-09-29T19:23:35.000Z","dependencies_parsed_at":null,"dependency_job_id":"1dc53411-f640-41c1-879e-c4905e8e9fdb","html_url":"https://github.com/YisusChrist/codecrafters-shell-rust","commit_stats":null,"previous_names":["yisuschrist/codecrafters-shell-rust"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YisusChrist%2Fcodecrafters-shell-rust","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YisusChrist%2Fcodecrafters-shell-rust/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YisusChrist%2Fcodecrafters-shell-rust/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YisusChrist%2Fcodecrafters-shell-rust/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/YisusChrist","download_url":"https://codeload.github.com/YisusChrist/codecrafters-shell-rust/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243514224,"owners_count":20303082,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["codecrafters","rust"],"created_at":"2024-11-19T18:51:16.704Z","updated_at":"2025-10-19T09:06:00.475Z","avatar_url":"https://github.com/YisusChrist.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![progress-banner](https://backend.codecrafters.io/progress/shell/40f0e925-eba2-4b76-b771-736de6880073)](https://app.codecrafters.io/users/codecrafters-bot?r=2qF)\n\nThis is a starting point for Rust solutions to the\n[\"Build Your Own Shell\" Challenge](https://app.codecrafters.io/courses/shell/overview).\n\nIn this challenge, you'll build your own POSIX compliant shell that's capable of\ninterpreting shell commands, running external programs and builtin commands like\ncd, pwd, echo and more. Along the way, you'll learn about shell command parsing,\nREPLs, builtin commands, and more.\n\n**Note**: If you're viewing this repo on GitHub, head over to\n[codecrafters.io](https://codecrafters.io) to try the challenge.\n\nTable of Contents\n\n- [Introduction](#introduction)\n- [Repository Setup](#repository-setup)\n- [Passing the first stage](#passing-the-first-stage)\n- [Stage 2 \\\u0026 beyond](#stage-2--beyond)\n- [Functionalities implemented for each stage](#functionalities-implemented-for-each-stage)\n  - [Basic functionality](#basic-functionality)\n    - [Stage 1: Print a prompt](#stage-1-print-a-prompt)\n      - [Your Task](#your-task)\n      - [Tests](#tests)\n      - [Notes](#notes)\n    - [Stage 2: Handle missing commands](#stage-2-handle-missing-commands)\n      - [Your Task](#your-task-1)\n      - [Tests](#tests-1)\n      - [Notes](#notes-1)\n    - [Stage 3: REPL](#stage-3-repl)\n      - [Your Task](#your-task-2)\n      - [Tests](#tests-2)\n      - [Notes](#notes-2)\n    - [Stage 4: The exit builtin](#stage-4-the-exit-builtin)\n      - [Your Task](#your-task-3)\n      - [Tests](#tests-3)\n      - [Notes](#notes-3)\n    - [Stage 5: The echo builtin](#stage-5-the-echo-builtin)\n      - [Your Task](#your-task-4)\n      - [Tests](#tests-4)\n    - [Stage 6: The type builtin: builtins](#stage-6-the-type-builtin-builtins)\n      - [Your Task](#your-task-5)\n      - [Tests](#tests-5)\n      - [Notes](#notes-4)\n    - [Stage 7: The type builtin: executable files](#stage-7-the-type-builtin-executable-files)\n      - [Your Task](#your-task-6)\n      - [Tests](#tests-6)\n      - [Notes](#notes-5)\n    - [Stage 8: Run a program](#stage-8-run-a-program)\n      - [Your Task](#your-task-7)\n      - [Tests](#tests-7)\n      - [Notes](#notes-6)\n  - [Navigation](#navigation)\n    - [Stage 9: The pwd builtin](#stage-9-the-pwd-builtin)\n      - [Your Task](#your-task-8)\n      - [Tests](#tests-8)\n      - [Notes](#notes-7)\n    - [Stage 10: The cd builtin: Absolute paths](#stage-10-the-cd-builtin-absolute-paths)\n      - [Your Task](#your-task-9)\n      - [Tests](#tests-9)\n      - [Notes](#notes-8)\n    - [Stage 11: The cd builtin: Relative paths](#stage-11-the-cd-builtin-relative-paths)\n      - [Your Task](#your-task-10)\n      - [Tests](#tests-10)\n      - [Notes](#notes-9)\n    - [Stage 12: Home directory](#stage-12-home-directory)\n      - [Your Task](#your-task-11)\n      - [Tests](#tests-11)\n      - [Notes](#notes-10)\n\n# Introduction\n\nWelcome to the Build your own Shell challenge!\n\nA shell is a command-line interface that executes commands and manages processes. In this challenge, you'll build your own POSIX compliant shell that's capable of interpreting shell commands, running external programs and builtin commands like cd, pwd, echo and more.\n\nAlong the way, you'll learn about shell command parsing, REPLs, builtin commands, and more.\n\n# Repository Setup\n\nWe've prepared a starter repository with some Rust code for you.\n\nStep 1: Clone the repository.\n\n```sh\ngit clone https://git.codecrafters.io/fec44321de99f891 codecrafters-shell-rust\ncd codecrafters-shell-rust\n```\n\nStep 2: Push an empty commit.\n\n```sh\ngit commit --allow-empty -m 'test'\ngit push origin master\n```\n\nWhen you run the above command, the \"Listening for a git push\" message below will change, and the first stage will be activated.\n\n# Passing the first stage\n\nThe entry point for your `shell` implementation is in `src/main.rs`. Study and\nuncomment the relevant code, and push your changes to pass the first stage:\n\n```sh\ngit add .\ngit commit -m \"pass 1st stage\" # any msg\ngit push origin master\n```\n\nTime to move on to the next stage!\n\n# Stage 2 \u0026 beyond\n\nNote: This section is for stages 2 and beyond.\n\n1. Ensure you have `cargo (1.70)` installed locally\n2. Run `./your_shell.sh` to run your program, which is implemented in\n   `src/main.rs`. This command compiles your Rust project, so it might be slow\n   the first time you run it. Subsequent runs will be fast.\n3. Commit your changes and run `git push origin master` to submit your solution\n   to CodeCrafters. Test output will be streamed to your terminal.\n\n# Functionalities implemented for each stage\n\n## Basic functionality\n\nHere are the functionalities that you'll need to implement for each stage:\n\n### Stage 1: Print a prompt\n\n#### Your Task\n\nIn this stage, you'll implement printing a shell prompt (`$`) and waiting for user input.\n\n#### Tests\n\nThe tester will execute your program like this:\n\n```sh\n./your_shell.sh\n```\n\nThe tester will then check whether your shell prints the `$` prompt and waits for user input.\n\n#### Notes\n\n- There's a space after the `$` character in the prompt.\n- Your program must not exit after printing `$`, it should wait for user input.\n- We'll handle reading commands and executing them in later stages, this stage only deals with printing the prompt.\n\n### Stage 2: Handle missing commands\n\n#### Your Task\n\nIn this stage, you'll implement support for handling missing commands in your shell.\n\n#### Tests\n\nThe tester will execute your program like this:\n\n```sh\n./your_shell.sh\n```\n\nIt will then send the following command to your shell:\n\n```sh\n$ nonexistent\nnonexistent: command not found\n```\n\nThe tester will check whether your shell prints `\u003ccommand_name\u003e: command not found` for an unrecognized command.\n\n#### Notes\n\n- The command name will be a random string (like `missing_command_234`), so the response can't be hardcoded.\n- We'll handle executing \"valid\" commands like `echo`, `cd` etc. in later stages, this stage only deals with unrecognized commands.\n- In this stage it's okay if your program exits soon after printing the `\u003ccommand_name\u003e: command not found` message. In later stages we'll check for a REPL (Read-Eval-Print Loop), i.e. whether the shell prints a new prompt after processing each command.\n\n### Stage 3: REPL\n\n#### Your Task\n\nIn this stage, you'll implement a [REPL (Read-Eval-Print Loop)](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop).\n\nA REPL is an interactive loop that reads user input, evaluates it, prints the result, and then waits for the next input.\n\n#### Tests\n\nThe tester will execute your program like this:\n\n```sh\n./your_shell.sh\n```\n\nIt will then send a series of commands to your shell:\n\n```sh\n$ invalid_command_1\ninvalid_command_1: command not found\n$ invalid_command_2\ninvalid_command_2: command not found\n$ invalid_command_3\ninvalid_command_3: command not found\n$\n```\n\nAfter each command, the tester will check if `\u003ccommand_name\u003e: command not found` is printed, and whether a prompt is printed for the next command.\n\n#### Notes\n\n- The exact number of commands sent and the command names will be random.\n- Just like the previous stages, all commands will be invalid commands, so the response will always be `\u003ccommand_name\u003e: command not found`.\n\n### Stage 4: The exit builtin\n\n#### Your Task\n\nIn this stage, you'll implement the [exit](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#exit) builtin.\n\n#### Tests\n\nThe tester will execute your program like this:\n\n```sh\n./your_shell.sh\n```\n\nIt'll then send an invalid command to your shell, followed by the `exit` command:\n\n```sh\n$ invalid_command_1\ninvalid_command_1: command not found\n$ exit 0\n```\n\nAfter issuing the `exit 0` command, the tester will verify whether your program terminates with [code/status](https://en.wikipedia.org/wiki/Exit_status) 0.\n\n#### Notes\n\n- The tester will always pass in `0` as the argument to the `exit` command.\n\n### Stage 5: The echo builtin\n\n#### Your Task\n\nIn this stage, you'll implement the [echo](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html) builtin.\n\n#### Tests\n\nThe tester will execute your program like this:\n\n```sh\n./your_shell.sh\n```\n\nIt'll then send a series of `echo` commands to your shell:\n\n```sh\n$ echo hello world\nhello world\n$ echo pineapple strawberry\npineapple strawberry\n$\n```\n\nAfter each command, the tester will check if the `echo` command correctly prints the provided text back.\n\n### Stage 6: The type builtin: builtins\n\n#### Your Task\n\nIn this stage, you'll implement the `type` builtin command for your shell.\n\nThe `type` builtin is used to determine how a command would be interpreted if used. Example:\n\n```sh\n$ type echo\necho is a shell builtin\n$ type exit\nexit is a shell builtin\n$ type nonexistent\nnonexistent: not found\n$ type cat\ncat is /bin/cat\n```\n\nIn this stage we'll only test two cases: builtin commands and unrecognized commands. We'll handle executable files in later stages.\n\n#### Tests\n\nThe tester will execute your program like this:\n\n```sh\n./your_shell.sh\n```\n\nIt'll then send a series of `type` commands to your shell:\n\n```sh\n$ type echo\necho is a shell builtin\n$ type exit\nexit is a shell builtin\n$ type type\ntype is a shell builtin\n$ type nonexistent\nnonexistent: not found\n$\n```\n\nThe tester will check if the `type` command responds correctly based on the command provided:\n\n- If a command is a shell builtin, the expected output is `\u003ccommand\u003e is a shell builtin`.\n- If a command is not recognized, the expected output is `\u003ccommand\u003e: not found`.\n\n#### Notes\n\n- The tester will only check for builtin commands and unrecognized commands in this stage.\n- `type` itself is a shell builtin command, so `$ type type` should print `type is a shell builtin`.\n\n### Stage 7: The type builtin: executable files\n\n#### Your Task\n\nIn this stage, you'll extend the `type` builtin to search for executable files using [PATH](\u003chttps://en.wikipedia.org/wiki/PATH_(variable)\u003e).\n\n[PATH](\u003chttps://en.wikipedia.org/wiki/PATH_(variable)\u003e) is an environment variable that specifies a set of directories where executable programs are located. When a command is received, the program should search for the command in the directories listed in the PATH environment variable. If the command is found, the program should print the path to the command. If the command is not found, the program should print `\u003ccommand\u003e: not found`.\n\n#### Tests\n\nThe tester will execute your program with a custom `PATH` like this:\n\n```sh\nPATH=\"/usr/bin:/usr/local/bin\" ./your_shell.sh\n```\n\nIt'll then send a series of `type` commands to your shell:\n\n```sh\n$ type ls\nls is /usr/bin/ls\n$ type abcd\nabcd is /usr/local/bin/abcd\n$ type missing_cmd\nmissing_cmd: not found\n$\n```\n\nThe tester will check if the `type` command correctly identifies executable files in the PATH.\n\n#### Notes\n\n- The actual value of the `PATH` environment variable will be random for each test case.\n- `PATH` can contain multiple directories separated by colons (`:`), your program should search for programs in each directory in order and return the first match.\n\n### Stage 8: Run a program\n\n#### Your Task\n\nIn this stage, you'll add support for running external programs with arguments.\n\nExternal programs are located using the `PATH` environment variable, as described in previous stages.\n\n#### Tests\n\nThe tester will execute your program like this:\n\n```sh\n./your_shell.sh\n```\n\nIt'll then send a command that you need to execute:\n\n```sh\n$ program_1234 alice\nHello alice! The secret code is 1234.\n```\n\nThe command (`program_1234`) in the example above will be present in `PATH` and will be an executable file.\n\nThe tester will check if your shell correctly executes the given command and prints the output.\n\n#### Notes\n\n- The program name, arguments and the expected output will be random for each test case.\n\n## Navigation\n\n### Stage 9: The pwd builtin\n\n#### Your Task\n\nIn this stage, you'll implement the `pwd` builtin command.\n\n[pwd](https://en.wikipedia.org/wiki/Pwd) stands for \"print working directory\".\n\n#### Tests\n\nThe tester will execute your program like this:\n\n```sh\n./your_shell.sh\n```\n\nIt'll then send a `pwd` command to your shell:\n\n```sh\n$ pwd\n/path/to/current/directory\n$\n```\n\nThe tester will check if the `pwd` command correctly prints the current working directory.\n\n#### Notes\n\n- The `pwd` command must print the full absolute path of the current working directory.\n\n### Stage 10: The cd builtin: Absolute paths\n\n#### Your Task\n\nIn this stage, you'll implement the `cd` builtin command to handle absolute paths.\n\nThe `cd` command is used to change the current working directory. `cd` can receive multiple argument types. In this challenge we'll cover:\n\n- Absolute paths, like `/usr/local/bin`. (This stage)\n- Relative paths, like `./`, `../`, `./dir`. (Later stages)\n- The `~` character, which stands for the user's home directory (Later stages)\n\n#### Tests\n\nThe tester will execute your program like this:\n\n```sh\n./your_shell.sh\n```\n\nIt'll then send a series of `cd` commands to your shell:\n\n```sh\n$ cd /usr/local/bin\n$ pwd\n/usr/local/bin\n$ cd /does_not_exist\ncd: /does_not_exist: No such file or directory\n$\n```\n\nThe tester will check if the `cd` command correctly changes the directory when a valid path is provided. It'll also check whether the message `cd: \u003cdirectory\u003e: No such file or directory` is printed if the provided path is invalid.\n\n#### Notes\n\n- The `cd` command doesn't print anything if the directory is changed successfully. The tester will use `pwd` to verify the current working directory after using `cd`.\n\n### Stage 11: The cd builtin: Relative paths\n\n#### Your Task\n\nIn this stage, you'll extend your `cd` builtin command to handle relative paths.\n\nAs a recap, `cd` can receive multiple argument types:\n\n- Absolute paths, like `/usr/local/bin`. (Previous stages)\n- Relative paths, like `./`, `../`, `./dir`. (This stage)\n- The `~` character, which stands for the user's home directory (Later stages)\n\n#### Tests\n\nThe tester will execute your program like this:\n\n```sh\n./your_shell.sh\n```\n\nIt'll then send a series of `cd` commands to your shell:\n\n```sh\n$ cd /usr\n$ pwd\n/usr\n$ cd ./local/bin\n$ pwd\n/usr/local/bin\n$ cd ../../\n$ pwd\n/usr\n$\n```\n\nThe tester will check if the `cd` command correctly changes the directory when a valid path is provided. It'll also check whether the message `cd: \u003cdirectory\u003e: No such file or directory` is printed if the provided path is invalid.\n\n#### Notes\n\n- The actual directory names used will be random, so you can't hardcode the expected output.\n- Relative paths like `./`, `../`, and more complex relative paths should be handled correctly.\n- The `cd` command doesn't print anything if the directory is changed successfully. The tester will use `pwd` to verify the current working directory after using `cd`.\n\n### Stage 12: Home directory\n\n#### Your Task\n\nIn this stage, you'll extend your `cd` builtin command to handle the `~` character.\n\nAs a recap, `cd` can receive multiple argument types:\n\n- Absolute paths, like `/usr/local/bin`. (Previous stages)\n- Relative paths, like `./`, `../`, `./dir`. (Previous stages)\n- The `~` character, which stands for the user's home directory (This stage)\n\nThe `~` character is shorthand for the user's home directory. When `cd` is received with `~`, your shell should change the current working directory to the user's home directory. The home directory is specified by the [`HOME`](https://unix.stackexchange.com/questions/123858/is-the-home-environment-variable-always-set-on-a-linux-system) environment variable.\n\n#### Tests\n\nThe tester will execute your program like this:\n\n```sh\n./your_shell.sh\n```\n\nIt'll then send a series of `cd` commands to your shell:\n\n```sh\n$ cd /usr/local/bin\n$ pwd\n/usr/local/bin\n$ cd ~\n$ pwd\n/home/user\n$\n```\n\nThe tester will check if the `cd` command correctly changes the directory to the user's home directory when `~` is used.\n\n#### Notes\n\n- The `pwd` command will be used to verify the current working directory after using `cd ~`.\n- The home directory is specified by the `HOME` environment variable.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyisuschrist%2Fcodecrafters-shell-rust","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyisuschrist%2Fcodecrafters-shell-rust","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyisuschrist%2Fcodecrafters-shell-rust/lists"}