Files
kugetsu/skills/kugetsu/SKILL.md
shokollm 5e968b6c4a feat(kugetsu): add config file initialization and documentation
- Initialize default ~/.kugetsu/config during kugetsu init
- Document config override options in SKILL.md
- Addresses han's review feedback
2026-04-01 22:12:27 +00:00

10 KiB

name, description, license, compatibility, metadata
name description license compatibility metadata
kugetsu Issue-driven session manager for opencode CLI. Manages base sessions and per-issue forked sessions with automatic indexing for headless orchestration. MIT Requires opencode CLI, bash, python3, and filesystem access.
author version
shoko 2.2

kugetsu - OpenCode Session Manager (Issue-Driven)

Manages opencode sessions with a base session + forked session pattern optimized for headless orchestration. Each issue gets an isolated git worktree to prevent workspace conflicts.

Installation

For Human Users

Run once on a new host:

. skills/kugetsu/scripts/kugetsu-install.sh

For Agents (Self-Install)

Copy the script to your PATH:

cp skills/kugetsu/scripts/kugetsu ~/.local/bin/kugetsu
chmod +x ~/.local/bin/kugetsu

Configuration

User overrides can be set in ~/.kugetsu/config. This file is sourced on each kugetsu command call, so changes take effect immediately without re-initialization.

A default config file is created during kugetsu init with commented examples:

# User configuration overrides
# Values set here take precedence over defaults
# Changes take effect immediately (no re-init needed)

# Max concurrent dev agents (default: 3)
# MAX_CONCURRENT_AGENTS=5

Available Config Options

Variable Default Description
MAX_CONCURRENT_AGENTS 3 Maximum number of concurrent dev agents

Architecture

Session Pattern

  • Base Session: Created once via TUI, used for forking dev agents
  • PM Agent Session: Created during init, persistent coordinator for task management
  • Forked Sessions: One per issue, branched from base via opencode run --fork --session <base>

Git Worktree Isolation

Each issue session gets its own git worktree to prevent conflicts:

  • Isolated working directory (no file collisions)
  • Isolated branch (no checkout conflicts)
  • Shared .git objects (efficient storage)

Directory Structure

~/.kugetsu/
├── sessions/
│   ├── base.json                    # Base session metadata
│   ├── pm-agent.json               # PM agent session metadata
│   └── github.com-shoko-kugetsu-14.json  # Forked session per issue
├── worktrees/
│   ├── github.com-shoko-kugetsu-14/     # Isolated workdir for issue #14
│   └── github.com-shoko-kugetsu-15/     # Isolated workdir for issue #15
└── index.json                       # Maps session IDs and issue refs to session files

Index File

{
  "base": "ses_abc123",
  "pm_agent": "ses_pm_xyz789",
  "issues": {
    "github.com/shoko/kugetsu#14": "github.com-shoko-kugetsu-14.json"
  }
}

Session File

{
  "type": "forked",
  "issue_ref": "github.com/shoko/kugetsu#14",
  "opencode_session_id": "ses_xyz789",
  "worktree_path": "/home/user/.kugetsu/worktrees/github.com-shoko-kugetsu-14",
  "created_at": "2026-03-29T18:16:10+02:00",
  "state": "idle"
}

Issue Ref Format

All issue references use the format: instance/user/repo#identifier

Examples:

  • github.com/shoko/kugetsu#14 (issue number)
  • github.com/shoko/kugetsu#-discuss (discussion, no issue number yet)
  • gitlab.com/username/project#42 (issue number)

Worktree Behavior

On kugetsu start

  1. Derives worktree path from issue ref: ~/.kugetsu/worktrees/{sanitized-ref}/
  2. If worktree exists: removes and recreates (guaranteed clean state)
  3. If worktree doesn't exist: creates fresh
  4. Clones repo, creates branch fix/issue-{id}
  5. Runs opencode with --workdir pointing to worktree

On kugetsu destroy

  1. Removes worktree via git worktree remove
  2. Deletes session file and index entry

Repo Configuration

If the repo URL cannot be derived from the issue ref, add to ~/.kugetsu/repos.json:

{
  "github.com/shoko kugetsu#14": "https://custom.repo.url/owner/repo.git"
}

Commands

kugetsu init [--force]

Initialize base + PM agent sessions via TUI:

kugetsu init
  • Requires a terminal (TTY) to spawn the opencode TUI
  • Creates base session and PM agent session
  • Stores both session IDs in index.json
  • Subsequent runs error unless --force is used

kugetsu start <issue-ref> <message> [--debug]

Start task for an issue by forking from base session:

kugetsu start github.com/shoko/kugetsu#14 "fix authentication bug"
kugetsu start github.com/shoko/kugetsu#-discuss "research auth options"
  • Creates isolated git worktree for the issue
  • Forks new session from base
  • Requires PM agent to exist (created by init)
  • Uses opencode run --fork --session <base-session-id> "<message>" --workdir <worktree>

kugetsu continue <issue-ref> <message> [--debug]

Continue work on an existing issue session:

kugetsu continue github.com/shoko/kugetsu#14 "add unit tests"
  • Looks up session file from index
  • Uses opencode run --continue --session <opencode-session-id> "<message>" --workdir <worktree>

kugetsu list

List all tracked sessions:

kugetsu list

Output:

ISSUE_REF                                          TYPE      SESSION_ID              WORKTREE
────────────────────────────────────────────────────────────────────────────────────────────────────────
(base)                                             base      ses_abc123              N/A
(pm-agent)                                         pm_agent   ses_pm_xyz789           N/A
github.com/shoko/kugetsu#14                        forked     ses_xyz789              /home/user/.kugetsu/worktrees/github.com-shoko-kugetsu-14

kugetsu prune [--force]

Remove orphaned sessions and worktrees:

kugetsu prune              # Shows what would be deleted
kugetsu prune --force      # Deletes orphaned items
  • Orphaned = session files or worktrees not in index
  • Always keeps base.json and pm-agent.json
  • Useful after opencode session cleanup

kugetsu destroy <issue-ref> [-y]

Delete session and worktree for specific issue:

kugetsu destroy github.com/shoko/kugetsu#14     # Prompts for confirmation
kugetsu destroy github.com/shoko/kugetsu#14 -y  # Skips confirmation

kugetsu destroy --pm-agent [-y]

Delete PM agent session (requires explicit --pm-agent):

kugetsu destroy --pm-agent -y

kugetsu destroy --base [-y]

Delete base session (requires explicit --base):

kugetsu destroy --base -y

Note: Destroying base also destroys PM agent since PM depends on base.

Workflow Example

# First-time setup (requires TTY)
kugetsu init
# Creates: base session + pm-agent session

# Start work on issue
kugetsu start github.com/shoko/kugetsu#14 "implement feature X"
# Creates: worktree at ~/.kugetsu/worktrees/github.com-shoko-kugetsu-14/

# Continue later
kugetsu continue github.com/shoko/kugetsu#14 "add tests"

# Continue again
kugetsu continue github.com/shoko/kugetsu#14 "fix failing test"

# List all sessions
kugetsu list

# Clean up orphaned items
kugetsu prune --force

# Delete session and worktree when done
kugetsu destroy github.com/shoko/kugetsu#14

Headless Operation

This design solves the headless CLI limitation discovered in Issue #14:

  1. Problem: opencode run --session <new> doesn't work headlessly (SSE stream terminates)
  2. Solution: Fork from existing base session, which works headlessly

The pattern:

  • Base session created once via TUI (interactive)
  • PM agent session created during init (persistent coordinator)
  • All subsequent work uses --fork --session <base> or --continue --session <forked>
  • Each session works in isolated git worktree

Recovery

If opencode sessions become out of sync:

  1. kugetsu list shows tracked sessions
  2. kugetsu prune removes orphaned files and worktrees
  3. For full reset: kugetsu destroy --base -y && kugetsu init

Remote Access via SSH (Optional)

To access kugetsu from a remote machine, SSH setup is required.

Automated Setup

Run the SSH setup script inside your container:

chmod +x skills/kugetsu/scripts/sshd-setup.sh
bash skills/kugetsu/scripts/sshd-setup.sh <username>

Omit <username> to use default user kugetsu.

What It Does

  • Checks systemd prerequisite
  • Creates non-root user
  • Configures SSH for key-only authentication
  • Enables passwordless sudo for the user
  • Starts sshd via systemd

After Setup

  1. Add your SSH public key to ~/.ssh/authorized_keys on the container
  2. Configure port forwarding on the host (see docs/kugetsu-setup.md)
  3. Connect: ssh -p 2222 <username>@<host-ip>

Remote Usage

Once connected via SSH, kugetsu works the same as local:

kugetsu list
kugetsu start github.com/shoko/kugetsu#14 "fix bug"
kugetsu continue github.com/shoko/kugetsu#14

Documentation

See docs/kugetsu-setup.md for full remote access setup including host-side port forwarding and firewall configuration.

Tailscale VPN (Alternative)

If your host does not have a public IP or you need access across different networks, Tailscale provides a VPN solution.

Benefits:

  • No public IP required
  • Each container gets its own unique Tailscale IP
  • Access from anywhere via Tailscale network
  • Normal internet access still works

Setup:

chmod +x skills/kugetsu/scripts/tailscale-setup.sh
bash skills/kugetsu/scripts/tailscale-setup.sh <username> <device-name>

The script will:

  1. Install Tailscale (supports Debian/Ubuntu, Fedora)
  2. Start the tailscaled daemon
  3. Prompt for AUTHKEY or browser-based login
  4. Configure device name (defaults to current hostname)

After Setup:

  • From any Tailscale device: ssh <username>@<device-name>
  • Works across different networks without port forwarding

See docs/kugetsu-setup.md for full Tailscale setup documentation.

Without kugetsu

If kugetsu is not available, use opencode directly:

# Create base session (requires TTY)
opencode
# Note the session ID from: opencode session list

# Fork for issue
opencode run --fork --session <base-session-id> "task"

# Continue
opencode run --continue --session <forked-session-id> "continue"

Tradeoff: No issue mapping, no index, manual session tracking, no worktree isolation.