Openship Project Linking: How to Use `openship init` to Connect Local Directories
The openship init command binds your current working directory to an Openship project by creating a .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 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 follows a strict schema defined in the CLI source. According to apps/cli/src/commands/init.ts, the file contains:
projectId(mandatory): The unique identifier of the selected Openship projectnameandslug: Optional human-readable identifiers fetched from the APIcontext: The active OpenShip context retrieved viagetActiveContext(), tying the link to specific API credentialsdefaults.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 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.jsonfile 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 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 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) 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
pickedvariable. - Non-interactive mode: When
--projectis supplied, the CLI validates the ID against the fetched list or uses it directly, bypassing the picker entirely.
3. Writing the .openship/project.json File
Once selected, the command assembles a ProjectLink object (lines 99-105) and persists it to disk:
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 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 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:
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.
Non‑Interactive Linking for CI/CD
In automation pipelines where interactive prompts fail, use flags to link deterministically:
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:
openship init --force
The --force flag bypasses the existing-link check (lines 47-50 in init.ts) and regenerates the configuration.
Verifying the Link
Inspect the generated file to confirm the link details:
cat .openship/project.json
Expected output:
{
"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:
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: Contains theinitCommandimplementation, handling argument parsing, project selection logic, and file persistence.apps/cli/src/lib/project-link.ts: ImplementsreadProjectLink()andfindProjectLinkPath(), providing the discovery mechanism used byopenship deployand other commands.apps/cli/src/lib/api-client.ts: Supplies thepaginatefunction 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.jsonfile containing the project ID, context, and default environment settings. readProjectLink()inapps/cli/src/lib/project-link.tsenables location-agnostic discovery by walking up the directory tree.- Interactive and non-interactive modes support both local development and CI/CD automation.
- The
--forceflag 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 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 recursively searches parent directories until it finds a .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 file already exists (as implemented in lines 47-50 of 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →