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
16 changes: 11 additions & 5 deletions docs/docs/explanation/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ An **instance** is Headjack's central concept. It represents a complete, isolate
- A **container** that provides an isolated execution environment
- One or more **sessions** that provide persistent terminal access

When you run `hjk run feature-branch`, Headjack creates an instance by wiring these three components together. The instance remains linked to your repository and branch throughout its lifecycle.
When you run `hjk run feature-branch`, Headjack creates the instance (worktree and container). Then `hjk agent` or `hjk exec` creates sessions within that instance. The instance remains linked to your repository and branch throughout its lifecycle.

import ThemedImage from '@theme/ThemedImage';
import useBaseUrl from '@docusaurus/useBaseUrl';
Expand Down Expand Up @@ -68,19 +68,25 @@ The session abstraction allows agents and shells to coexist. A typical workflow

## The Data Flow

When you run a command like `hjk run feature-branch`, here's how data flows through the system:
Instance creation and session management are separate operations.

### Creating an Instance (`hjk run`)

1. **Repository identification**: Headjack opens your git repository and computes a stable identifier from the remote URL or path

2. **Worktree creation**: A new worktree is created at `~/.local/share/headjack/git/<repo-id>/<branch>`, checking out the specified branch

3. **Container launch**: A container starts with the worktree mounted at `/workspace`. The container runs `sleep infinity` as its init process, keeping it alive indefinitely

4. **Session creation**: A tmux session starts inside the container, running the specified agent CLI (or shell)
4. **Catalog persistence**: The instance metadata is written to `~/.local/share/headjack/catalog.json`

### Starting Sessions (`hjk agent` / `hjk exec`)

1. **Instance lookup**: Headjack finds the instance for the specified branch

5. **Catalog persistence**: The instance metadata is written to `~/.local/share/headjack/catalog.json`
2. **Session creation**: A tmux session starts inside the container, running the specified agent CLI or shell

6. **Terminal attachment**: Your terminal attaches to the tmux session
3. **Terminal attachment**: Your terminal attaches to the tmux session (unless `-d` detached mode is used)

When you detach (Ctrl+B, D), the session continues running in the container. The agent keeps working. When you `hjk attach` later, you reconnect to that same session and see everything that happened while you were away.

Expand Down
51 changes: 34 additions & 17 deletions docs/docs/explanation/session-lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,44 @@ The session abstraction provides:

## Session Creation

When you run `hjk run feature-branch`, Headjack creates both an instance and an initial session:
Sessions are created separately from instances. First, `hjk run` creates the instance:

```
+------------------------------------------------------------+
| hjk run |
| | |
| +-------------+-------------+ |
| v v v |
| Create worktree Launch Create session |
| container | |
| | | | |
| v v |
| Create worktree Launch container |
| | | |
| +-------------+-------------+ |
| v |
| Instance running |
| with one session |
| (no sessions yet) |
+------------------------------------------------------------+
```

Then `hjk agent` or `hjk exec` creates sessions within that instance:

```
+------------------------------------------------------------+
| hjk agent / hjk exec |
| | |
| v |
| Create tmux session |
| | |
| v |
| Attach terminal |
+------------------------------------------------------------+
```

The session is created in "detached" mode, meaning tmux starts the session but doesn't attach your terminal. Then Headjack immediately attaches, giving the appearance of a single operation.

You can also create additional sessions in an existing instance:
You can create multiple sessions in an existing instance:

```bash
# Create a shell session while a Claude session is running
hjk session create my-instance --type shell
hjk exec feat/auth
```

This creates a second tmux session in the same container. Both sessions share the container's filesystem, network, and resources.
Expand Down Expand Up @@ -116,13 +129,14 @@ Headjack tracks when you last accessed each session. This enables the "most rece
Each `hjk attach` without a session name attaches to that instance's most recently used session:

```bash
# Create instance with claude session
hjk run feature-a
# Create instance and start claude session
hjk run feat/auth
hjk agent feat/auth claude

# Later: detach (Ctrl+B, D)

# Reattach to the same (MRU) session
hjk attach feature-a
hjk attach feat/auth
```

### Global MRU
Expand All @@ -131,14 +145,16 @@ Running `hjk attach` with no arguments attaches to the globally most recently us

```bash
# Work on feature-a
hjk run feature-a
hjk run feat/auth
hjk agent feat/auth claude
# Detach

# Work on feature-b
hjk run feature-b
hjk run feat/api
hjk agent feat/api claude
# Detach

# Resume most recent work (feature-b)
# Resume most recent work (feat/api)
hjk attach
```

Expand Down Expand Up @@ -230,18 +246,19 @@ Sessions can be named for easier reference:

```bash
# Auto-generated name (e.g., "happy-panda")
hjk session create my-instance
hjk agent feat/auth claude

# Custom name
hjk session create my-instance --name testing
hjk agent feat/auth claude --name auth-impl
hjk exec feat/auth --name debug-shell
```

Names must be unique within an instance. The auto-generated names use a word list to create memorable combinations.

Named sessions can be attached by name:

```bash
hjk attach my-instance --session testing
hjk attach feat/auth auth-impl
```

## Session State Machine
Expand Down
6 changes: 4 additions & 2 deletions docs/docs/how-to/authenticate.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ If not found:
After authentication, verify by running an agent:

```bash
hjk run my-feature --agent claude # or gemini, codex
hjk run feat/test
hjk agent feat/test claude # or gemini, codex
```

The agent should authenticate without prompting for login.
Expand All @@ -112,7 +113,8 @@ To switch between subscription and API key:

```bash
hjk auth claude # Select the other option
hjk rm my-feature && hjk run my-feature # Recreate instance with new credentials
hjk rm feat/test && hjk run feat/test # Recreate instance with new credentials
hjk agent feat/test claude
```

## Notes
Expand Down
4 changes: 2 additions & 2 deletions docs/docs/how-to/build-custom-image.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,10 @@ Use the `--image` flag:
hjk run feat/auth --image my-registry.io/my-custom-headjack:latest
```

Combine with `--agent`:
Then start an agent session:

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

### Set as permanent default
Expand Down
79 changes: 58 additions & 21 deletions docs/docs/how-to/manage-sessions.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,51 +8,81 @@ description: Start, monitor, and manage agent and shell sessions in isolated con

This guide covers the complete session lifecycle: starting agent and shell sessions, attaching and detaching, and monitoring background sessions.

## Create an instance first

Before starting any sessions, create an instance for your branch:

```bash
hjk run feat/auth
```

This creates a git worktree for the branch and a container with the worktree mounted. The instance is now ready for sessions.

## Start an agent session

Run an LLM coding agent (Claude, Gemini, or Codex) with a prompt:

```bash
hjk run feat/auth --agent claude "Implement JWT authentication"
hjk agent feat/auth claude --prompt "Implement JWT authentication"
```

This creates a git worktree for the branch, a container with the worktree mounted, and starts the agent with your prompt. The terminal attaches automatically.
The terminal attaches automatically to the agent session.

### Start without a prompt

Run an agent in interactive mode:

```bash
hjk run fix/header-bug --agent gemini
hjk agent fix/header-bug gemini
```

### Choose an agent

Specify the agent with `--agent`:
Specify the agent as the second argument:

```bash
hjk run feat/api --agent claude "Add rate limiting"
hjk run feat/api --agent gemini "Add rate limiting"
hjk run feat/api --agent codex "Add rate limiting"
hjk agent feat/api claude --prompt "Add rate limiting"
hjk agent feat/api gemini --prompt "Add rate limiting"
hjk agent feat/api codex --prompt "Add rate limiting"
```

## Start a shell session

Run an interactive shell without an agent:
Run an interactive shell using `hjk exec`:

```bash
hjk run feat/auth
hjk exec feat/auth
```

This creates the same isolated environment but drops you into a shell instead of starting an agent. Useful for manual debugging or running commands alongside agent sessions.
This opens a bash shell inside the container. Useful for manual debugging or running commands alongside agent sessions.

### Run a command

Execute a specific command:

```bash
hjk exec feat/auth npm test
hjk exec feat/auth npm run build
```

### Direct execution (no tmux)

For quick commands without session persistence, use `--no-mux`:

```bash
hjk exec feat/auth --no-mux ls -la
hjk exec feat/auth --no-mux pwd
```

This prints output directly to your terminal without creating a tmux session.

## Run in detached mode

Start any session in the background with `-d`:

```bash
hjk run feat/auth --agent claude -d "Refactor the auth module"
hjk run feat/auth -d # detached shell
hjk agent feat/auth claude -d --prompt "Refactor the auth module"
hjk exec feat/auth -d npm run build
```

Use `hjk logs` or `hjk attach` to monitor or interact later.
Expand All @@ -62,9 +92,15 @@ Use `hjk logs` or `hjk attach` to monitor or interact later.
Start multiple agents on different branches, each in its own isolated container:

```bash
hjk run feat/auth --agent claude -d "Implement JWT authentication"
hjk run feat/api --agent claude -d "Add rate limiting to the API"
hjk run fix/header-bug --agent gemini -d "Fix the header rendering bug"
# Create instances first
hjk run feat/auth
hjk run feat/api
hjk run fix/header-bug

# Then start agents in detached mode
hjk agent feat/auth claude -d --prompt "Implement JWT authentication"
hjk agent feat/api claude -d --prompt "Add rate limiting to the API"
hjk agent fix/header-bug gemini -d --prompt "Fix the header rendering bug"
```

Monitor all running instances:
Expand All @@ -78,9 +114,9 @@ hjk ps
Run multiple agents within a single instance using `--name`:

```bash
hjk run feat/auth --agent claude -d --name auth-impl "Implement the auth module"
hjk run feat/auth --agent claude -d --name auth-tests "Write tests for the auth module"
hjk run feat/auth --name debug-shell # add a shell session
hjk agent feat/auth claude -d --name auth-impl --prompt "Implement the auth module"
hjk agent feat/auth claude -d --name auth-tests --prompt "Write tests for the auth module"
hjk exec feat/auth --name debug-shell # add a shell session
```

All sessions share the same git worktree but run independently.
Expand Down Expand Up @@ -150,13 +186,14 @@ hjk logs feat/auth happy-panda --full # complete log
### Custom session name

```bash
hjk run feat/auth --agent claude --name jwt-implementation "Implement JWT"
hjk agent feat/auth claude --name jwt-implementation --prompt "Implement JWT"
hjk exec feat/auth --name build-session npm run build
```

### Custom container image

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

:::note
Expand All @@ -165,7 +202,7 @@ Using `--image` bypasses devcontainer detection. If your repository has a `devco

## Troubleshooting

**"no sessions exist"** - No sessions are running. Start one with `hjk run`.
**"no sessions exist"** - No sessions are running. Start one with `hjk agent` or `hjk exec`.

**"no instance found for branch"** - The branch doesn't have an instance. Create one with `hjk run <branch>`.

Expand Down
9 changes: 5 additions & 4 deletions docs/docs/how-to/recover-from-crash.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ feat/api running 2 1h ago

## Resume a stopped instance

If the container stopped but the instance still exists, simply run a new session:
If the container stopped but the instance still exists, simply start a new session:

```bash
hjk run feat/auth --agent claude "Continue where we left off"
hjk agent feat/auth claude --prompt "Continue where we left off"
```

Headjack automatically restarts the container and creates a new session. Your git worktree is preserved with all previous work.
Expand All @@ -55,7 +55,7 @@ hjk kill feat/auth/stuck-session
Then start a fresh session:

```bash
hjk run feat/auth --agent claude
hjk agent feat/auth claude
```

## Force remove a broken instance
Expand All @@ -69,7 +69,8 @@ hjk rm feat/auth --force
This removes the instance from Headjack's catalog and cleans up the worktree. You can then start fresh:

```bash
hjk run feat/auth --agent claude
hjk run feat/auth
hjk agent feat/auth claude
```

## Recover work from the worktree
Expand Down
4 changes: 2 additions & 2 deletions docs/docs/how-to/stop-cleanup.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ Stop the container but preserve the worktree:
hjk stop feat/auth
```

The instance remains in the catalog. Resume it later by running any `hjk run` command for that branch:
The instance remains in the catalog. Resume it later by running any command for that branch—Headjack automatically restarts stopped instances:

```bash
hjk run feat/auth --agent claude "Continue working on auth"
hjk agent feat/auth claude --prompt "Continue working on auth"
```

## Kill a specific session
Expand Down
Loading