# Openship Project Linking: How to Use `openship init` to Connect Local Directories

> Learn Openship project linking using openship init. Connect local directories to your Openship project effortlessly and deploy with ease. Simplify your workflow.

- Repository: [oblien/openship](https://github.com/oblien/openship)
- Tags: how-to-guide
- Published: 2026-07-21

---

**The `openship init` command binds your current working directory to an Openship project by creating a [`.openship/project.json`](https://github.com/oblien/openship/blob/main/.openship/project.json) file that stores the project identifier and context, allowing subsequent CLI commands like `openship deploy` to automatically target the correct project without requiring explicit `--project` flags.**

Openship project linking establishes a persistent connection between your local codebase and a remote Openship deployment target through a simple CLI workflow. The `openship init` command, implemented in the `oblien/openship` repository, generates a hidden configuration file that stores your project metadata and active API context. This eliminates the need to repeatedly pass project identifiers and ensures consistent deployment environments across your development workflow.

## What `openship init` Does

The `openship init` command serves as the entry point for **project linking** in the Openship CLI. When executed, it creates a [`.openship/project.json`](https://github.com/oblien/openship/blob/main/.openship/project.json) file in your target directory (or current working directory) containing the selected project ID, optional metadata, and default environment settings. This file acts as a persistent reference that downstream commands automatically read to determine which project to operate on.

### The Project Link File Structure

The generated [`.openship/project.json`](https://github.com/oblien/openship/blob/main/.openship/project.json) follows a strict schema defined in the CLI source. According to [`apps/cli/src/commands/init.ts`](https://github.com/oblien/openship/blob/main/apps/cli/src/commands/init.ts), the file contains:

- **`projectId`** (mandatory): The unique identifier of the selected Openship project
- **`name`** and **`slug`**: Optional human-readable identifiers fetched from the API
- **`context`**: The active OpenShip context retrieved via `getActiveContext()`, tying the link to specific API credentials
- **`defaults.environment`**: The default deployment environment (defaults to `"production"` unless overridden by `--environment`)

### Command Options and Flags

The `initCommand` definition in [`apps/cli/src/commands/init.ts`](https://github.com/oblien/openship/blob/main/apps/cli/src/commands/init.ts) exposes several configuration options:

- **`--project <id>`**: Skip interactive selection and link directly to the specified project ID
- **`--environment <name>`**: Set the default environment for subsequent deployments (default: `production`)
- **`--dir <path>`**: Target a specific directory instead of the current working directory
- **`--force`**: Overwrite an existing [`.openship/project.json`](https://github.com/oblien/openship/blob/main/.openship/project.json) file without prompting
- **`--json`**: Output the result as JSON instead of a human-readable message

## Step‑by‑Step Linking Process

The linking implementation in [`apps/cli/src/commands/init.ts`](https://github.com/oblien/openship/blob/main/apps/cli/src/commands/init.ts) follows a predictable four-phase architecture:

### 1. Fetching Available Projects

If no `--project` flag is provided, the CLI queries the OpenShip API to retrieve accessible projects. The command uses the `paginate` helper from [`apps/cli/src/lib/api-client.ts`](https://github.com/oblien/openship/blob/main/apps/cli/src/lib/api-client.ts) to iterate through the `/projects` endpoint. If the API returns no projects, the command exits with instructions to create a project in the Openship dashboard.

### 2. Selecting the Target Project

The selection logic (lines 55-88 in [`init.ts`](https://github.com/oblien/openship/blob/main/init.ts)) supports two modes:

- **Interactive mode**: The CLI renders a numbered list of available projects. You select by entering the list number or pasting the full project ID. The choice is stored in a `picked` variable.
- **Non-interactive mode**: When `--project` is supplied, the CLI validates the ID against the fetched list or uses it directly, bypassing the picker entirely.

### 3. Writing the [`.openship/project.json`](https://github.com/oblien/openship/blob/main/.openship/project.json) File

Once selected, the command assembles a `ProjectLink` object (lines 99-105) and persists it to disk:

```bash
mkdirSync(root, { recursive: true })
writeFileSync(linkPath, JSON.stringify(link, null, 2) + '\n')

```

This creates the `.openship/` directory if missing and writes the pretty-printed JSON configuration.

### 4. Reading the Link in Subsequent Commands

Other CLI commands rely on `readProjectLink()` from [`apps/cli/src/lib/project-link.ts`](https://github.com/oblien/openship/blob/main/apps/cli/src/lib/project-link.ts) to discover the project context. The `findProjectLinkPath()` utility walks up the directory tree from the current working directory until it locates a [`.openship/project.json`](https://github.com/oblien/openship/blob/main/.openship/project.json) file. This location-agnostic lookup allows you to run Openship commands from any subdirectory of your project. If the file is missing or unreadable, the function returns `null`, prompting the CLI to request explicit project flags.

## Practical Usage Examples

### Interactive Project Selection

For standard development workflows, run the command without arguments to trigger the interactive picker:

```bash
cd /path/to/my-app
openship init

```

The CLI lists available projects (e.g., `[1] My API`, `[2] Frontend App`), prompts for selection, and writes the configuration to [`./.openship/project.json`](https://github.com/oblien/openship/blob/main/./.openship/project.json).

### Non‑Interactive Linking for CI/CD

In automation pipelines where interactive prompts fail, use flags to link deterministically:

```bash
openship init --project proj_ABC123 --environment staging --force

```

This command skips the interactive picker, sets the default deploy environment to `staging`, and overwrites any existing link file.

### Overwriting an Existing Link

To replace an existing project association without manually deleting files:

```bash
openship init --force

```

The `--force` flag bypasses the existing-link check (lines 47-50 in [`init.ts`](https://github.com/oblien/openship/blob/main/init.ts)) and regenerates the configuration.

### Verifying the Link

Inspect the generated file to confirm the link details:

```bash
cat .openship/project.json

```

Expected output:

```json
{
  "projectId": "proj_ABC123",
  "name": "My Awesome Project",
  "slug": "my-awesome-project",
  "context": "default",
  "defaults": { "environment": "production" }
}

```

You can also read the link programmatically using the project-link utility:

```typescript
import { readProjectLink } from "openship/src/lib/project-link";

const link = readProjectLink(); // Searches upward from process.cwd()
console.log(link?.projectId);   // -> "proj_ABC123"

```

## Key Source Files in the Openship Repository

Understanding the implementation details requires familiarity with these specific files in the `oblien/openship` repository:

- **[`apps/cli/src/commands/init.ts`](https://github.com/oblien/openship/blob/main/apps/cli/src/commands/init.ts)**: Contains the `initCommand` implementation, handling argument parsing, project selection logic, and file persistence.
- **[`apps/cli/src/lib/project-link.ts`](https://github.com/oblien/openship/blob/main/apps/cli/src/lib/project-link.ts)**: Implements `readProjectLink()` and `findProjectLinkPath()`, providing the discovery mechanism used by `openship deploy` and other commands.
- **[`apps/cli/src/lib/api-client.ts`](https://github.com/oblien/openship/blob/main/apps/cli/src/lib/api-client.ts)**: Supplies the `paginate` function used to fetch project lists from the OpenShip API during the selection phase.

## Summary

Openship project linking via `openship init` creates a seamless bridge between local directories and remote projects:

- The command generates a [`.openship/project.json`](https://github.com/oblien/openship/blob/main/.openship/project.json) file containing the project ID, context, and default environment settings.
- `readProjectLink()` in [`apps/cli/src/lib/project-link.ts`](https://github.com/oblien/openship/blob/main/apps/cli/src/lib/project-link.ts) enables location-agnostic discovery by walking up the directory tree.
- Interactive and non-interactive modes support both local development and CI/CD automation.
- The `--force` flag allows safe re-linking without manual file deletion.

## Frequently Asked Questions

### What file does `openship init` create?

The command creates a hidden [`.openship/project.json`](https://github.com/oblien/openship/blob/main/.openship/project.json) file in your target directory (or current working directory). This JSON file stores the `projectId`, optional project metadata, active API context, and default environment settings that subsequent Openship CLI commands reference automatically.

### Can I use `openship init` in a subdirectory of my project?

Yes. The `findProjectLinkPath()` utility in [`apps/cli/src/lib/project-link.ts`](https://github.com/oblien/openship/blob/main/apps/cli/src/lib/project-link.ts) recursively searches parent directories until it finds a [`.openship/project.json`](https://github.com/oblien/openship/blob/main/.openship/project.json) file. This allows you to run `openship deploy` or other commands from any nested folder within your project tree while still referencing the correct project configuration.

### How do I override an existing project link?

Use the `--force` flag when running `openship init`. Without this flag, the CLI aborts with an error if a [`.openship/project.json`](https://github.com/oblien/openship/blob/main/.openship/project.json) file already exists (as implemented in lines 47-50 of [`apps/cli/src/commands/init.ts`](https://github.com/oblien/openship/blob/main/apps/cli/src/commands/init.ts)). The force option overwrites the existing file with the new project selection.

### What happens if I don't specify a project ID?

If you omit the `--project` flag, the CLI enters interactive mode. It fetches your accessible projects from the OpenShip API using the `paginate` helper and presents them as a numbered list. You must select a project by number or ID to proceed. If no projects exist in your account, the command exits with guidance to create one via the Openship dashboard.