Create a new project


skuba can guide you through an interactive prompt to initialise a new directory and Git repository for your project. It includes a set of starter templates that reflect the typical components of a core SEEK service.


skuba init

Creates a new local project from a starter template.

skuba init does not provision any resources in AWS, Buildkite or GitHub on its own, and only requires a connection to the public npm registry. Most of its built-in templates start you off with a Buildkite pipeline that should be ready to go once you push your repository to GitHub and configure Buildkite.

Option Description
--debug Enable debug console output
--non-interactive Read JSON config from stdin instead of prompting
--help, -h Show help for the command

Interactive walkthrough

Let’s start by running the command:

skuba init

and answering a few starter questions:

? For starters, some project details:
βŠ™          Owner : SEEK-Jobs/my-team
βŠ™           Repo : my-repo
βŠ™       Platform : arm64
βŠ™ Default Branch : main

# ...

skuba init will initialise your CODEOWNERS file and a few others based on the specified owner. GitHub teams can be found at the following URL:

github.com/orgs/SEEK-Jobs/teams/my-team/repositories

You’re now presented with a selection of templates:

? Select a template:
❯ greeter
  oss-npm-package
  github β†’
  seek β†’
  local β†’

Use the ↑ ↓ arrow keys, then ⏎ enter your selection.

The selected template will prompt you to fill out some additional fields. You can skip these for now to get your bearing:

This template uses the following information:

- Prod Buildkite queue

? Fill this in now? …
  yes
❯ no

Templating has been skipped. Resume it later by running skuba init in the new directory.

skuba init will take a while to install some initial dependencies, after which you’ll have a new directory to work with:

Initialized empty Git repository in /my-repo/.git/
Installing dependencies...

βœ” All done! Try running:

cd my-repo
git push --set-upstream origin main

You can now proceed to the next steps.

Adding to an existing repository

If you run skuba init from inside an existing pnpm workspace (detected via a root pnpm-workspace.yaml), it offers to scaffold the new project as an additional workspace project rather than a standalone repository. Any template works in this mode, whether it’s a package or an application such as a Lambda worker or an API. Because detection is based on your location, skuba init asks you to confirm before switching modes; the prompt defaults to No, so press Enter (or answer No) to create a standalone repository instead.

Yarn/npm workspaces and plain Git repositories are not offered this mode and keep the standalone behaviour.

This mode asks for a project name and a project directory relative to the workspace root. repoName keeps naming the repository that hosts the project.

In this mode skuba init:

  • Skips git init, remote configuration and the git push --set-upstream guidance; the existing repository is reused.
  • Leaves configuration that the workspace root owns in place rather than duplicating it into the project: .gitignore, .prettierignore, .prettierrc.js, eslint.config.js, .dockerignore, .npmrc, .nvmrc, Renovate config, and the .github and .vscode directories.
  • Registers the project in the root pnpm-workspace.yaml when it isn’t already matched by an existing glob, and installs dependencies against the root lockfile. The edit is applied through the file’s syntax tree, so surrounding keys, comments and formatting are preserved. Only pnpm workspaces are supported in this mode.
  • Answers the template field that names the projectβ€”serviceName for services and moduleName for packagesβ€”from the project name instead of asking for it twice. Where a template validates the field, such as private-npm-package requiring an @seek/ scope, the project name pre-fills the prompt rather than replacing it.
  • Commits just the new project’s files.

Running skuba init outside of a repository (or answering No to the prompt) keeps the standalone behaviour described above.

Non-interactive execution

skuba init is interactive by default. For non-interactive execution, pipe in JSON:

skuba init << EOF
{
  "destinationDir": "tmp-greeter",
  "templateComplete": true,
  "templateData": {
    "ownerName": "my-org/my-team",
    "prodBuildkiteQueueName": "123456789012:cicd",
    "platformName": "arm64",
    "repoName": "tmp-greeter",
    "defaultBranch": "main"
  },
  "templateName": "greeter"
}
EOF

skuba init reads this JSON automatically when stdin is not a TTY.

Pass --non-interactive to require piped input and never fall back to an interactive prompt. If stdin is a TTY, skuba init --non-interactive prints the expected JSON Schema and exits instead of prompting.

–

Next steps

Now that you’ve run skuba init, where does that leave you?

Git repository

Let’s review the Git repository that has been initialised to see what’s in there:

git log
# Clone greeter
# Initial commit

git remote get-url origin
# git@github.com:<org>/<repo>.git

skuba has committed its initial template files and configured a remote origin for you. You should create the corresponding repository on GitHub and push to it. Replace main with your default branch name as appropriate:

git push --set-upstream origin main

Directory structure

Familiarise yourself with the directory structure that skuba has created:

β”œβ”€β”€ .buildkite
β”œβ”€β”€ .github
β”œβ”€β”€ .vscode
└── src
    β”œβ”€β”€ app.test.ts
    β”œβ”€β”€ app.ts
β”œβ”€β”€ .dockerignore
β”œβ”€β”€ .gitignore
β”œβ”€β”€ .nvmrc
β”œβ”€β”€ Dockerfile
β”œβ”€β”€ eslint.config.js
β”œβ”€β”€ oxfmt.config.ts
β”œβ”€β”€ README.md
β”œβ”€β”€ docker-compose.yml
β”œβ”€β”€ vitest.config.ts
β”œβ”€β”€ package.json
β”œβ”€β”€ pnpm-lock.yaml
β”œβ”€β”€ pnpm-workspace.yaml
β”œβ”€β”€ skuba.template.js
β”œβ”€β”€ tsconfig.build.json
β”œβ”€β”€ tsconfig.json

A few points to call out:

  • There are configuration files aplenty for the various tools we use in skuba and more broadly at SEEK.
  • The .buildkite directory houses a CI/CD pipeline that should be ready to go once you push your repository to GitHub and configure Buildkite.
  • The src directory contains our source code, which is later compiled to lib.
  • package.json lists your project dependencies and scripts.

CLI commands

Try out some of the commands documented throughout this CLI section.

skuba lint may be a good starting point:

skuba lint

Templating

If you skipped templating earlier, skuba lint will complain that you haven’t finished it. Resume templating by re-running skuba init from inside the project directory:

cd my-repo
skuba init

It detects the leftover skuba.template.js, prompts for the fields you skipped, fills in the placeholder values across your project, and removes skuba.template.js.

README checklist

Each built-in template has a README.md that contains a checklist of next steps to take your project to production.