# Nail

![nail logo](https://user-images.githubusercontent.com/10245964/233905871-c1947748-a7dc-4514-a01d-2e0c9446cca9.png)

Nail is a command-line tool that integrates LLM's generative capabilities into the development workflow. It can be used to quickly draft new files, modify existing code, debug errors, build unit tests, and more.

### Why use Nail?

Chat is currently the main way of interfacing with LLMs. This is great for many general use cases, but in a software development use case this leads to tedious manual copy and pasting of code and context. Nail bypasses chat and brings automated code generation into the place that developers are already working.

![nail basics demo](https://user-images.githubusercontent.com/10245964/234179828-c84ad757-3392-4df6-b6be-147ff337405b.gif)

### Why not Copilot/Tabnine etc?

Use both! Nail is complementary to these in-editor extensions. Nail is better suited for some situations such as whole-file generation, sweeping changes and refactors of existing files, and debugging. Editor extensions are likely more efficient for small adjustments to existing code.

### Can I send this code straight to production?

Please don't. The code generated by LLMs can vary in quality and your mileage may vary depending on coding language, LLM model, and problem complexity. That said, generated code can provide a great starting point and can help spark ideas for new approaches. Review all generated code and treat it with the same skepticism that you would for code written by another human being.

## Installation

To install Nail, you can use pip:

```
pip3 install nail
```

This will install the required dependencies and make the `nail` command available in your terminal.

## Configuration

Before using Nail, you need to configure it with your OpenAI API key. You can do this by running:

```
nail configure
```

This will prompt you to enter your API key, which will be saved for future use.

## Basic Usage

Once you have configured Nail, you can begin using it to generate code. To get started create and navigate to a new project directory. Create a new file and write out what you want the code in that file to do. For example:

```
# calculator.py
A python class with addition, subtraction, and multiplication methods
```

Once you have created and saved your file, run the following command:

```
nail build calculator.py
```

After a moment, Nail will generate code meeting that specification and will prompt you to accept or reject the proposed code. If you accept, it will be saved to the file.

What if we want to add to this file? Use the following command to ask Nail to add an additional method.

```
nail modify calculator.py -r "Add a division method"
```

Nail will then generate the changes and propose them as a diff that, if accepted, will be saved to the file. Continue reading below to learn about further ways to use Nail to assist in the coding process.

## Usage Details

Nail provides several commands to help you with your code:

### 🔨 Build 🔨

To build a new file with optional context files, use the `build` command:

```
nail build <file> [--context-files <file1> <file2> ...] [--model <model>]
```

The target file should contain a description of the file that you are trying to build. The more specific the specification, the more accurate the result. As an example:

```
A python script with a function that does the following:
- accepts a URL string as a parameter
- raises an error if the URL is invalid
- scrapes the specified page for heading tags
- returns an array of resulting headings
```

If the file does not exist, nail will open your default editor to fill in the prompt in-line.

The `--context-files` (or `-c`) option can be used to pass in one or more additional files that could provide useful reference. For example, you can pass in files containing modules that should be imported and used by the new file that is being built.

### 🔧 Modify 🔧

To modify an existing file, use the `modify` command:

```
nail modify <file> [--request <request>] [--context-files <file1> <file2> ...] [--model <model>]
```

The request should be in the form of a command, such as "Add a new function that..." or "Refactor the existing class to...".

### 🐛 Debug 🐛

To debug an existing file, use the `debug` command:

```
nail debug <file> [--error <error_message>] [--model <model>]
```

If an error message is not passed, this command will simply look for any possible issues in the given file.

### 🧪 Generate Unit Tests 🧪

To generate a unit test file for an existing file, use the `spec` command:

```
nail spec <file> <target_path> [--model <model>]
```

Once they have been generated, test files can be further adjusted with the `modify` command.

### 🧐 Explain a File 🧐

To explain the contents of a file, use the `explain` command:

```
nail explain <file> [--context-files <file1> <file2> ...] [--verbose] [--model <model>]
```

Output will be displayed in the console. More detailed explanations will be generated if the `--verbose` (or `-v`) flag is included.

### 📖 Generate README 📖

To generate a README file for your project, use the `readme` command:

```
nail readme [--model <model>]
```

This command will gather all application files into context automatically. It will exclude a number of files irrelevant to a README, such as tests and licenses. Please note, this currently only works for relatively small projects given the limited context window available for GPT.

## Customization

There may be situations in which you want Nail to apply specific additional instructions to the LLM. For example, when using the spec tool, you may wish to specify that tests are always written using a specific library. Or, you may wish to define style guidelines that the build and modify commands should always adhere to. Whatever the case, you can configure each Nail command with additional instructions.

To do this, create a `.nail.yaml` file inside your project's root directory. There is a `.sample.nail.yaml` file inside of this repository showing the appropriate format. For any commands you would like to customize, simply add any desired instructions and they will be appended to requests to the LLM.

For example:

```
prompt_instructions:
  spec: Use rspec for all unit tests.
  build: |
    Do not include inline comments.
    Avoid deeply nested conditionals wherever possible.
```

## Models

Nail currently supports the following models:

- gpt-3.5-turbo (default)
- gpt-4

You can specify the model to use with the `--model` (or `-m`) option for each command.

## Development

To install Nail locally for development, clone the repo, then run this command from within the project directory:

```
pip3 install -e .
```

Run the test suite using `pytest`.

## License

This project is licensed under the MIT License.
