Skip to content

xaaha/hulak

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Hulak Logo

File based API client for terminal nerds.

Elevator Pitch

If you’ve ever wanted to manage your API workflows like a code repository, easily searching, editing, copying, and deleting request files and variables, hulak is the tool for you. Hulak is a fast, lightweight, file-based API client that lets you make API calls and organize requests and responses using YAML files.

# ────────────────────────────────────────────────────
# Example: test_gql.hk.yaml
# ────────────────────────────────────────────────────
---
method: POST

# 🚨 Keep secrets separate! Avoid hardcoding credentials.
url: "{{.graphqlUrl}}"
headers:
  Content-Type: application/json
  # 🔍 Dynamically access nested values from another file
  # using the `getValueOf` action.
  Authorization: Bearer {{getValueOf "data.access_token" "employer_auth.json"}}
body:
  graphql:
    # đź“‚ Store large JSON, GraphQL, XML, or HTML files separately
    # and access them using the `getFile` action.
    query: '{{getFile "e2etests/test_collection/test.graphql"}}'
    variables:
      # 🏷️ Use templating to dynamically construct values.
      name: "{{.userName}} of age {{.userAge}}"
      age: "{{.userAge}}"
# Run the file using secrets from staging.env file
hulak -env staging -f test_gql

Table of Contents

Getting Started

Installation

1. Homebrew

brew install xaaha/tap/hulak

2. go install

  • Run
go install github.com/xaaha/hulak@latest
  • You need to install go in your system

  • In order for any utility, installed with go install, to be available for use, you need the path from go env GOPATH to be in the shell’s PATH.

    • If it’s not, add the following to your shell's configuration file.

export GOPATH=$HOME/go
export PATH=$PATH:$(go env GOPATH)/bin
  • Then source your shell configuration file source ~/.zshrc or source ~/.bashrc

3. Build from source

  • Clone the repo
  • Install required dependencies: Run go mod tidy in the root of the project
  • Build the executable with: go build -o hulak
  • Move the executable to the path.
    • On Mac/Linux: sudo mv hulak /usr/local/bin/
      • Verify the project exists in path with: which hulak
    • On Windows:
      • Move the hulak.exe binary to a folder that is in your PATH. A common location for this is C:\Go\bin (or another directory you've added to your PATH).
      • To add a folder to your PATH in Windows: Go to Control Panel > System and Security > System > Advanced system settings. Click Environment Variables. Under System variables, find the Path variable and click Edit. Add the path to your folder (e.g., C:\Go\bin) and click OK.

Verify Installation with

hulak version
# or
hulak help

Initialize Project

Create a project directory and cd into it. Then Initialize the project

mkdir my_apis & cd my_apis
hulak init

Hulak uses env directory to store secrets (e.g., passwords, client IDs) used in API call. It allows separation between different environments like local, test, and production environments. The hulak init command above sets up the secrets directory structure env/ and also provides an apiOptions.yaml file for your reference.

# to create multiple .env files in the env directory run
hulak init -env staging prod

You can store all secrets in global.env, but for running tests with different credentials, use additional <custom_file_name>.env files like staging.env or prod.env.

If env/global.env is absent, it will prompt you to create one at runtime. For more details read this environment documentation.

# example directory structure
env/
  global.env    # default and required created with hulak init
  prod.env      # user defined, could be anything
  staging.env   # user defined
collection/     # example directory
    test.yaml   # example api file

Using OS environment variables

If you use a .env file to store secrets, you might not want to duplicate secrets already stored in your system environment (for example, your shell). To avoid this, you can reference system environment variables in your .env file by using the $ prefix.

For example, if you had an environment variable USER=foo set on your system, and the following was in your <custom_file_name>.env file.

exampleVar = $USER

Using {{.exampleVar}} within a request file, i.e.

# test.yaml
method: Get
url: http://some.api.com/tests?bar={{.exampleVar}}

would result in the request targeting http://some.api.com/tests?bar=foo

Create An API file

Then Basic API call looks like test.yaml below. See full documentation on Request Body structure here. More request examples are here.

# test.yaml
method: Get
url: https://jsonplaceholder.typicode.com/todos/1

Run the file with

hulak -env global -f test
# or
hulak -env global -fp test.yaml

Since global is default environment, we don't need to specify -env global. So, this is the simplest way of running the file.

hulak -f test

File's response is be printed in the console and also saved at the same location as the calling file with _response.json suffix. Read more about response in response documentation.

{
  "body": {
    "completed": false,
    "id": 1,
    "title": "delectus aut autem",
    "userId": 1
  },
  "status": "200 OK"
}

Flags and Subcommands

Flags

Flag Description Usage
-env Specify the environment file you want to use for Api Call. If the user flag is absent, it defaults to global. -env prod
-fp Represents file-path for the file/directory you want to run. -fp "./collection/getUsers.yaml"
-f File name (yaml/yml) to run. Hulak searches your directories and subdirectories from the root and finds the matching yaml file(s). If multiple matches are found, they run concurrently -f graphql
-debug Add debug boolean flag to get the entire request, response, headers, and TLS info about the api request -debug
-dir Run entire directory concurrently. Only supports (.yaml or .yam) file. All files use the same provided environment -dir path/to/directory/
-dirseq Run entire directory one file at a time. Only supports (.yaml or .yam) file. All files use the same provided environment. In nested directory, it is not guranteed that files will run as they appear in the file system. If the order matter, it's recommended to have a directory without nested directories inside it, in which case, files will run alphabetically -dirseq path/to/directory/

Subcommands

Subcommand Description Usage
help display help message hulak help
init Initialize environment directory and files in it hulak init or hulak init -env global prod staging
migrate migrates postman environment and collection (v2.1 only) files for hulak. hulak migrate "path/to/environment.json" "path/to/collection.json

Schema

To enable auto-completion for Hulak YAML files, you have the following options:

Note: You need a YAML language server for any of these options to work.

Option 1: Schema Store (Recommended)

The Hulak schema is now available in the Schema Store. If your editor supports Schema Store (most do, like VS Code and Neovim with yaml-language-server), auto-completion will work automatically for files ending in .hk.yaml or .hk.yml. If Schema Store is not set up in your editor, use Option 2 or Option 3 below.

Option 2: Declare Schema in the File

You can declare the schema at the top of your YAML file. This can either be a local schema or a schema referenced by a URL. Here are two examples:

Local Schema

# yaml-language-server: $schema=../../assets/schema.json
---

OR

# yaml-language-server: $schema=https://raw.githubusercontent.com/xaaha/hulak/refs/heads/main/assets/schema.json
---

Option 3: Configure Your Editor

Alternatively, you can configure your editor to enable auto-completion without needing to declare the schema in each file. For Neovim users, you can find my configuration here. Once configured, you can simply rename your file to yourFile.hk.yaml for auto-completion.

Actions

Actions make it easier to retrieve values from other files. See, actions documentation for more detailed explanation.

.Key

# example section
body:
  graphql:
    query: |
      query Hello($name: String!, $age: Int) {
        hello(person: { name: $name, age: $age })
      }
    variables:
      name: "{{.userName}} of age {{.userAge}}"
      age: "{{.userAge}}"

.Key is a variable, that is present in one of the .env files. It grabs the value from environemnt files in the env/ directory in the root of the project created above. The value of, Key is replaced during runtime. In the example above, .userName and .userAge are examples of retrieving key from secrets stored in env/.

getValueOf:

# example
url: `{{getValueOf "key" "file_name" }}`

getValueOf looks for the value of the key inside the file_name.json file. Since responses of the api requests are saved in file_name_response.json file in the same directory, you don't need to provide _response.json suffix when using getValueOf. If multiple file_name.json is found, hulak recurces through the directory and uses the first file match. So, it's recommended that you use a unique name for each file. You can also provide the exact file location instead of file_name as ./e2etests/test_collection/graphql_response.json

  • "key" and "file_name": Should be surrounded by double quotes (Go template).
  • key you are looking for could in a nested object as well. For example, user.name means give me the name inside the user's object. You can esacpe the dot (.) with single curly brace like {user.name}. Here, user.name is considered a key.
  • file_name could be the only file name or the entire file path from project root. If only name is provided, first match will be used.
# name is inside the user object in the user.json file
name: '{{getValueOf "user.name" "user.json"}}'
# extract the value of name from nested object from provided json file path
name: '{{getValueOf "data.users[0].name" "e2etests/test_collection/graphql_response.json"}}'
# where name is the key in the file
name: `{{getValueOf "name" "user.json"}}`

getFile

Gets the file content as string and dumps the entire file content in context. It takes file path as an argument. Do not use getFile action to pass token in auth header.

# example
body:
  graphql:
    query: '{{getFile "e2etests/test_collection/test.graphql"}}'

Learn more about these actions here

Auth2.0 (Beta)

Hualk supports auth2.0 web-application-flow. Follow the auth2.0 provider instruction to set it up. Read more here

Planned Features

See Features and Fixes Milestone to see all the upcoming, exciting features

Support the Project

If you enjoy the project, please consider supporting it by reporting a bug, suggesting a feature request, or sponsoring the project. Your pull request contributions are also welcome. Feel free to open an issue indicating your interest in tackling a bug or implementing a new feature.

About

Lightweight file-based API client for terminal nerds

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages