Skip to main content
Thank you for your interest in contributing to Tank! Every contribution matters — whether it’s fixing a typo, improving docs, reporting a bug, or building a feature.

Project Status

Tank is MVP code-complete with 461 TypeScript tests and 16 Python tests passing. The most valuable contributions right now are:
  1. Testing the CLI and web app in real workflows
  2. Opening issues for bugs, edge cases, or missing features
  3. Improving documentation — clarity, examples, diagrams
  4. Contributing security analysis rules for the audit system

Getting Started

Prerequisites

Development Setup

1

Clone the repository

git clone https://github.com/tankpkg/tank.git
cd tank
2

Install dependencies

corepack enable
pnpm install
3

Configure environment

cp .env.example .env.local
Fill in the values — see .env.example for what’s needed.
4

Push database schema

cd apps/web
npx drizzle-kit push
Requires DATABASE_URL in .env.local.
5

Start development server

pnpm dev --filter=web
6

Run tests

pnpm test              # All tests (461 TypeScript + 16 Python)
pnpm test --filter=cli # CLI tests only
pnpm test --filter=web # Web tests only
See Local Development Setup for detailed instructions.

How to Contribute

Report a Bug

Use the Bug Report template on GitHub. Include:
  • Expected behavior — What you thought would happen
  • Actual behavior — What actually happened
  • Steps to reproduce — How to trigger the bug
  • Environment — OS, Node version, Tank version

Suggest a Feature

Open a Feature Request or start a Discussion. Before opening:
  • Check existing issues to avoid duplicates
  • Consider if it fits Tank’s core mission (security-first package management)

Submit Code

1

Fork the repository

Click “Fork” on the Tank repository.
2

Create a branch

git checkout -b feat/my-feature
Use conventional branch names:
  • feat/ — New feature
  • fix/ — Bug fix
  • docs/ — Documentation
  • chore/ — Tooling, config
  • test/ — Tests
  • refactor/ — Code refactoring
3

Make your changes

Write clear, focused commits following the Commit Message Guidelines.
4

Push your branch

git push origin feat/my-feature
5

Open a Pull Request

Go to the Tank repository and click “Compare & pull request”.

Pull Request Guidelines

Before Submitting

  • Keep PRs focused — One logical change per PR
  • Update documentation if your change affects user-facing behavior
  • Add tests for new functionality
  • Ensure all checks pass before requesting review
  • Follow existing patterns — Look at similar files for consistency

PR Description Template

## Summary
Brief description of what this PR does.

## Changes
- Bullet list of specific changes
- Include file paths when relevant

## Testing
How did you test this? What commands did you run?

## Related Issues
Fixes #123

Review Process

  1. Automated checks run (tests, linting)
  2. Maintainer reviews code
  3. Address feedback with new commits
  4. Once approved, maintainer merges

Commit Messages

We use Conventional Commits:
feat: add permission budget validation
fix: resolve lockfile hash mismatch on Windows
docs: clarify semver enforcement rules
chore: update CI workflow
test: add integration tests for install command
refactor: extract version resolution logic

Types

  • feat — New feature
  • fix — Bug fix
  • docs — Documentation
  • chore — Tooling, dependencies, config
  • test — Tests
  • refactor — Code refactoring (no behavior change)
  • perf — Performance improvement
  • ci — CI/CD changes
  • style — Formatting (no code change)

Format

type(scope): subject

[optional body]

[optional footer]
Examples:
# Simple
feat: add OIDC SSO support

# With scope
fix(cli): handle permission escalation on update

# With body
refactor(web): extract storage provider interface

Creates an abstraction layer for storage backends,
allowing on-prem deployments to use local filesystems
instead of Supabase Storage.

# With breaking change
feat!: require Node.js 24+

BREAKING CHANGE: Drop support for Node.js <24

Coding Standards

TypeScript/JavaScript

  • Strict TypeScript — No any, no @ts-ignore, no as any
  • TDD — Write failing tests first (RED → GREEN → REFACTOR)
  • ESM only"type": "module", no require()
  • 2-space indent, LF line endings — Enforced via .editorconfig
  • Import paths — Web app uses @/* alias, CLI uses relative .js extensions
  • Test files__tests__/*.test.ts (never .spec.ts)

Web App

  • Server Components by default'use client' only when needed
  • Tailwind CSS v4 via @tailwindcss/postcss
  • Zod for validation — Never trust raw input
  • Drizzle ORM — Never raw SQL or Prisma
  • react-doctor — React linting (60+ rules)

Python

  • Pydantic 2 for all models — Strict validation
  • pytest for testing — test_*.py pattern
  • Type hints on all functions

Anti-Patterns

Never do these:
  • Suppress types with as any, @ts-ignore, @ts-expect-error
  • Use .spec.ts (always .test.ts)
  • Import between apps (CLI ↔ Web) — use @tank/shared
  • Commit .env.local (contains secrets)
  • Use require() (ESM only)
  • Refactor while bugfixing (fix minimally)
  • Create DB connections outside lib/db.ts
  • Use Supabase for DB queries (Drizzle only)
  • Modify auth-schema.ts manually (auto-generated)

Project Structure

tank/
├── apps/
│   ├── cli/              # Tank CLI — Commander.js, 16 commands
│   │   ├── bin/tank.ts   # Entry point
│   │   └── src/
│   │       ├── commands/ # 1-file-per-command pattern
│   │       └── lib/      # API client, config, lockfile, packer
│   └── web/              # Next.js 15 registry + API
│       ├── app/          # App Router: (auth), (dashboard), (registry), api/
│       ├── lib/          # DB, auth, storage, email, audit
│       └── api-python/   # Python security scanner stubs
├── packages/
│   └── shared/           # Zod schemas, types, constants
├── python-api/           # FastAPI security scanner
│   └── lib/scan/         # 6-stage pipeline
├── e2e/                  # End-to-end tests
└── docs/                 # Product brief, architecture, roadmap

Where to Look

TaskLocationNotes
Add CLI commandapps/cli/src/commands/Export async fn, register in bin/tank.ts
Add API endpointapps/web/app/api/v1/Next.js Route Handler
Add UI pageapps/web/app/Route groups: (auth), (dashboard), (registry)
Modify DB schemaapps/web/lib/db/schema.tsRun drizzle-kit generate after
Add shared typepackages/shared/src/Export from index.ts
Add UI componentapps/web/components/ui/npx shadcn add <component>
Modify scannerpython-api/lib/scan/6 stages: stage0–stage5

Testing

Running Tests

# All tests
pnpm test

# Specific workspace
pnpm test --filter=cli
pnpm test --filter=web
pnpm test --filter=shared

# E2E tests (needs .env.local)
pnpm test:e2e

# Performance tests (needs real DB)
pnpm test:perf

Writing Tests

TypeScript (Vitest):
import { describe, it, expect } from 'vitest';

describe('feature', () => {
  it('should do something', () => {
    expect(true).toBe(true);
  });
});
Python (pytest):
def test_feature():
    assert True

Test Guidelines

  • TDD — Write test first (RED → GREEN → REFACTOR)
  • Descriptive namesshould validate permissions not test1
  • One assertion per test when possible
  • Arrange, Act, Assert pattern
  • No side effects — Tests should be independent

Code of Conduct

This project follows the Contributor Covenant Code of Conduct. In short:
  • Be respectful and inclusive
  • Focus on constructive feedback
  • Assume good intent
  • Report unacceptable behavior to [email protected]

License

By contributing, you agree that your contributions will be licensed under the MIT License.

Questions?

Open a Discussion — there are no dumb questions.

Next Steps

Setup

Set up your local development environment

Architecture

Understand the system design

Testing

Learn how to run and write tests

Build docs developers (and LLMs) love