- Initialize default ~/.kugetsu/config during kugetsu init - Document config override options in SKILL.md - Addresses han's review feedback
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. |
|
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
.gitobjects (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
- Derives worktree path from issue ref:
~/.kugetsu/worktrees/{sanitized-ref}/ - If worktree exists: removes and recreates (guaranteed clean state)
- If worktree doesn't exist: creates fresh
- Clones repo, creates branch
fix/issue-{id} - Runs opencode with
--workdirpointing to worktree
On kugetsu destroy
- Removes worktree via
git worktree remove - 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
--forceis 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.jsonandpm-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:
- Problem:
opencode run --session <new>doesn't work headlessly (SSE stream terminates) - 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:
kugetsu listshows tracked sessionskugetsu pruneremoves orphaned files and worktrees- 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
- Add your SSH public key to
~/.ssh/authorized_keyson the container - Configure port forwarding on the host (see docs/kugetsu-setup.md)
- 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:
- Install Tailscale (supports Debian/Ubuntu, Fedora)
- Start the tailscaled daemon
- Prompt for AUTHKEY or browser-based login
- 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.