Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions docs/docs/decisions/adr-006-oci-customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ This adds complexity:

**Pure OCI image approach**
- Ship a default base image with opinionated tooling
- Users override with `--base <image>` or `--base <Dockerfile>`
- Users override with `--image <image>` or `--image <Dockerfile>`
- All customization delegated to standard OCI tooling

This approach:
Expand All @@ -56,9 +56,10 @@ Use **OCI images exclusively** for environment customization. No first-class sup

The customization model is:

1. **Default**: Headjack ships a base image (`ghcr.io/headjack/base:latest`) with opinionated tooling
2. **Image override**: Users specify an alternative image via `--base <registry-image>`
3. **Dockerfile override**: Users specify a Dockerfile via `--base <path/to/Dockerfile>`
1. **Devcontainer (default)**: If a `devcontainer.json` exists, use it automatically
2. **Image override**: Users specify an alternative image via `--image <registry-image>`
3. **Dockerfile override**: Users specify a Dockerfile via `--image <path/to/Dockerfile>`
4. **Fallback**: If no devcontainer and no `--image`, use configured `default.base_image`

When a Dockerfile path is provided (detected by filename ending in `Dockerfile` or `Containerfile`), Headjack runs `container build` before launching the instance. Layer caching is handled by the container runtime.

Expand Down
6 changes: 3 additions & 3 deletions docs/docs/explanation/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ Currently, Headjack stores one set of credentials per agent type. Multi-account

### Container Filesystem Persistence

Once credentials are written inside a container, they persist until the container is recreated. A `hjk recreate` is needed to rotate credentials if they change on the host.
Once credentials are written inside a container, they persist until the container is recreated. Use `hjk rm` followed by `hjk run` to recreate an instance if credentials change on the host.

### OAuth Token Expiry

Expand All @@ -299,7 +299,7 @@ The token may have expired:

```bash
hjk auth claude # Re-capture fresh credential
hjk recreate <instance> # Recreate container with new credentials
hjk rm <instance> && hjk run <branch> # Recreate instance with new credentials
```

### Claude onboarding prompt
Expand All @@ -312,7 +312,7 @@ To switch authentication methods, simply run `hjk auth` again and select the oth

```bash
hjk auth claude # Select option 2 for API key
hjk recreate <instance> # Recreate to use new credential type
hjk rm <instance> && hjk run <branch> # Recreate instance with new credential type
```

## Why Not SSH Agent Forwarding?
Expand Down
25 changes: 17 additions & 8 deletions docs/docs/explanation/image-customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,17 +208,26 @@ Each instance uses a full container image. There's no Nix-style deduplication wh

Custom images must be built before use. For complex images, this can take minutes. Pre-building and pushing to a registry mitigates this.

## Image Variants
## Devcontainers vs Custom Images

The base image comes in variants for different use cases:
Headjack supports two approaches to environment customization:

| Variant | Features | Use Case |
|---------|----------|----------|
| `base` | Agent CLIs, version managers | Most development work |
| `systemd` | Adds systemd support | Projects requiring services |
| `dind` | Adds Docker-in-Docker | Testing Docker workflows |
### Devcontainers (Recommended)

Each variant extends the previous, adding capabilities at the cost of image size.
If your repository contains a `devcontainer.json`, Headjack uses it automatically. This is the preferred approach because:

- Configuration lives with the code
- Standard format understood by VS Code, GitHub Codespaces, and other tools
- Supports Dev Container Features for modular customization
- Team members get consistent environments automatically

### Custom Images

Build a custom OCI image when:

- Your repository doesn't have a devcontainer configuration
- You need to share the same image across multiple repositories
- You want faster startup (pre-built vs building at runtime)

## Best Practices

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/how-to/authenticate.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ To switch between subscription and API key:

```bash
hjk auth claude # Select the other option
hjk recreate my-feature # Recreate container with new credentials
hjk rm my-feature && hjk run my-feature # Recreate instance with new credentials
```

## Notes
Expand Down
28 changes: 10 additions & 18 deletions docs/docs/how-to/build-custom-image.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,14 @@ description: Build a custom container image with project dependencies and use it

# Build and Use Custom Images

Create a custom image with your project's dependencies pre-installed for faster container startup, or use one of the official Headjack image variants.
Create a custom image with your project's dependencies pre-installed for faster container startup.

## Use an official variant

Headjack provides three image variants:

```bash
# Base image (default) - minimal with agent CLIs
hjk run feat/auth --base ghcr.io/gilmanlab/headjack:base

# Systemd variant - includes init system
hjk run feat/auth --base ghcr.io/gilmanlab/headjack:systemd

# Docker-in-Docker variant - includes Docker daemon
hjk run feat/auth --base ghcr.io/gilmanlab/headjack:dind
```
:::tip Prefer Devcontainers
If your repository has a `devcontainer.json`, Headjack uses it automatically. You only need a custom image when:
- Your repository doesn't have a devcontainer configuration
- You want to share a pre-built image across multiple repositories
- You need faster startup than devcontainer building provides
:::

## Build a custom image

Expand Down Expand Up @@ -114,16 +106,16 @@ docker push ghcr.io/your-org/my-custom-headjack:latest

### Override for a single run

Use the `--base` flag:
Use the `--image` flag:

```bash
hjk run feat/auth --base my-registry.io/my-custom-headjack:latest
hjk run feat/auth --image my-registry.io/my-custom-headjack:latest
```

Combine with `--agent`:

```bash
hjk run feat/auth --base my-registry.io/my-custom-headjack:latest --agent claude "Implement the feature"
hjk run feat/auth --image my-registry.io/my-custom-headjack:latest --agent claude "Implement the feature"
```

### Set as permanent default
Expand Down
8 changes: 6 additions & 2 deletions docs/docs/how-to/manage-sessions.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,16 @@ hjk logs feat/auth happy-panda --full # complete log
hjk run feat/auth --agent claude --name jwt-implementation "Implement JWT"
```

### Custom base image
### Custom container image

```bash
hjk run feat/auth --agent claude --base my-registry.io/custom-image:latest
hjk run feat/auth --agent claude --image my-registry.io/custom-image:latest
```

:::note
Using `--image` bypasses devcontainer detection. If your repository has a `devcontainer.json`, it will be used automatically without needing `--image`.
:::

## Troubleshooting

**"no sessions exist"** - No sessions are running. Start one with `hjk run`.
Expand Down
7 changes: 4 additions & 3 deletions docs/docs/how-to/troubleshoot-auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,11 @@ hjk auth codex
hjk auth <agent> # Select option 2 and enter your API key
```

After re-authenticating, recreate your instance:
After re-authenticating, remove and recreate your instance to apply the new credentials:

```bash
hjk recreate my-feature
hjk rm my-feature
hjk run my-feature
```

## Keychain Access Issues
Expand Down Expand Up @@ -209,7 +210,7 @@ To switch authentication methods:

```bash
hjk auth claude # Select the other option when prompted
hjk recreate my-feature # Apply new credentials to existing instance
hjk rm my-feature && hjk run my-feature # Recreate instance with new credentials
```

## Related
Expand Down
66 changes: 0 additions & 66 deletions docs/docs/reference/cli/recreate.md

This file was deleted.

2 changes: 1 addition & 1 deletion docs/docs/reference/cli/rm.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,4 @@ Type `y` or `yes` to confirm, or any other input (including Enter) to cancel.

- [hjk stop](stop.md) - Stop without removing
- [hjk ps](ps.md) - List instances
- [hjk recreate](recreate.md) - Recreate container without removing worktree
- [hjk run](run.md) - Create a new instance
16 changes: 8 additions & 8 deletions docs/docs/reference/cli/run.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ hjk run <branch> [prompt] [flags]

## Description

Creates a new session within an instance for the specified branch. If no instance exists for the branch, one is created first by:
Creates a new session within an instance for the specified branch. If no instance exists for the branch, one is created first. The container environment is determined by:

- Creating a git worktree at the configured location
- Spawning a new container with the worktree mounted
1. **Devcontainer (default)**: If the repository contains a `devcontainer.json`, it is used to build and run the container environment automatically.
2. **Base image**: Use `--image` to specify a container image directly, bypassing devcontainer detection.

A new session is always created within the instance. If `--agent` is specified, the agent is started with an optional prompt. Otherwise, the default shell is started.

Expand All @@ -40,16 +40,16 @@ If an instance exists but is stopped, it is automatically restarted before creat
|------|-------|------|---------|-------------|
| `--agent` | | string | | Start the specified agent instead of a shell. Valid values: `claude`, `gemini`, `codex`. If specified without a value, uses the configured `default.agent`. |
| `--name` | | string | | Override the auto-generated session name |
| `--base` | | string | | Override the default base image |
| `--image` | | string | | Use a container image instead of devcontainer |
| `--detached` | `-d` | bool | `false` | Create session but do not attach (run in background) |

## Examples

```bash
# Create instance with shell session
# Auto-detect devcontainer.json (recommended)
hjk run feat/auth

# Create instance with Claude agent
# Start Claude agent in devcontainer
hjk run feat/auth --agent claude "Implement JWT authentication"

# Create additional session in existing instance
Expand All @@ -62,8 +62,8 @@ hjk run feat/auth --name debug-shell
hjk run feat/auth --agent claude -d "Refactor the auth module"
hjk run feat/auth --agent claude -d "Write tests for auth module"

# Use a custom base image
hjk run feat/auth --base my-registry.io/custom-image:latest
# Use a specific container image (bypasses devcontainer)
hjk run feat/auth --image my-registry.io/custom-image:latest

# Use default agent from config
hjk run feat/auth --agent
Expand Down
1 change: 0 additions & 1 deletion docs/docs/reference/cli/stop.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,3 @@ When an instance is stopped:
- [hjk run](run.md) - Restart a stopped instance
- [hjk rm](rm.md) - Remove an instance entirely
- [hjk ps](ps.md) - List instances and their status
- [hjk recreate](recreate.md) - Recreate the container
15 changes: 12 additions & 3 deletions docs/docs/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Default values applied when creating new instances.
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `default.agent` | string | `""` (empty) | Default agent to use. Valid values: `claude`, `gemini`, `codex`. Empty means no default. |
| `default.base_image` | string | `ghcr.io/gilmanlab/headjack:base` | Container image to use for instances. |
| `default.base_image` | string | `""` (empty) | Fallback container image when no devcontainer is found. If empty and no devcontainer.json exists, `hjk run` will error with guidance. |

### agents

Expand Down Expand Up @@ -74,7 +74,7 @@ A complete configuration file with all options:
```yaml
default:
agent: claude
base_image: ghcr.io/gilmanlab/headjack:base
base_image: "" # Empty by default; set if you want a fallback when no devcontainer exists

agents:
claude:
Expand Down Expand Up @@ -144,8 +144,17 @@ The following environment variables override their corresponding configuration k
Headjack validates configuration values when loading and setting them:

- `default.agent` must be one of: `claude`, `gemini`, `codex` (or empty)
- `default.base_image` is required and cannot be empty
- `default.base_image` is optional; if empty, a devcontainer.json must exist in the repository
- `runtime.name` must be one of: `podman`, `docker`
- All storage paths are required

Invalid values will result in an error message describing the validation failure.

## Devcontainer Priority

When running `hjk run`, Headjack determines the container environment as follows:

1. If `--image` is specified, use that image (bypasses devcontainer detection)
2. If a `devcontainer.json` exists in the repository, use devcontainer mode
3. If `default.base_image` is configured, use that image
4. Otherwise, error with guidance on how to configure the environment
4 changes: 2 additions & 2 deletions docs/docs/reference/environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ These environment variables override values in the configuration file. They foll
| Variable | Type | Description | Overrides |
|----------|------|-------------|-----------|
| `HEADJACK_DEFAULT_AGENT` | string | Default agent for new instances | `default.agent` |
| `HEADJACK_BASE_IMAGE` | string | Default container image | `default.base_image` |
| `HEADJACK_BASE_IMAGE` | string | Fallback container image when no devcontainer exists | `default.base_image` |
| `HEADJACK_MULTIPLEXER` | string | Terminal multiplexer | `default.multiplexer` |
| `HEADJACK_WORKTREE_DIR` | string | Worktree storage directory | `storage.worktrees` |

Expand All @@ -25,7 +25,7 @@ These environment variables override values in the configuration file. They foll
# Use Claude as the default agent
export HEADJACK_DEFAULT_AGENT=claude

# Use a custom container image
# Set a fallback container image (used when no devcontainer.json exists)
export HEADJACK_BASE_IMAGE=myregistry.com/myimage:latest

# Override worktree directory
Expand Down
10 changes: 7 additions & 3 deletions docs/docs/tutorials/custom-image.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,17 +226,21 @@ Type `exit` to leave the container.

## Step 9: Use the Image with Headjack

Now use your custom image with Headjack. Specify it with the `--base` flag:
Now use your custom image with Headjack. Specify it with the `--image` flag:

```bash
hjk run feat/new-feature --base my-app-headjack:latest --agent claude "Add user authentication using PostgreSQL sessions"
hjk run feat/new-feature --image my-app-headjack:latest --agent claude "Add user authentication using PostgreSQL sessions"
```

The agent starts immediately with all dependencies available. No waiting for Python or Node.js installation.

:::note
Using `--image` bypasses devcontainer detection. If your repository has a `devcontainer.json`, you typically don't need a custom image—just run `hjk run feat/new-feature` and the devcontainer will be used automatically.
:::

## Step 10: Set as Default

To avoid specifying `--base` every time, set your image as the default:
To avoid specifying `--image` every time, set your image as the default:

```bash
hjk config default.base_image my-app-headjack:latest
Expand Down
1 change: 0 additions & 1 deletion docs/sidebars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ const sidebars: SidebarsConfig = {
'reference/cli/stop',
'reference/cli/kill',
'reference/cli/rm',
'reference/cli/recreate',
'reference/cli/auth',
'reference/cli/config',
'reference/cli/version',
Expand Down
Loading