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
5 changes: 5 additions & 0 deletions .agent/workflows/branch.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ git checkout -b {type}/{description}

- Use lowercase with hyphens: `feature/user-authentication`
- Be descriptive but concise: `bugfix/login-timeout` not `bugfix/fix`
- Start with an action verb for clarity:
- New functionality: `feature/add-user-dashboard`
- Enhancing existing: `feature/improve-search-filters`
- Fixing: `bugfix/fix-login-timeout`
- Removing: `feature/remove-legacy-api`
- Include issue number if applicable: `bugfix/123-login-timeout`
- Release branches use version: `release/1.2.0` (semver format)

Expand Down
35 changes: 35 additions & 0 deletions .agent/workflows/git-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ tools:
- **Purpose**: Ensure safe, traceable git workflow for all file changes
- **Trigger**: Read this when conversation indicates file creation/modification in a git repo
- **Principle**: Every change on a branch, never directly on main
- **CRITICAL**: With parallel sessions, ALWAYS verify branch state before ANY file operation

**First Actions** (before any code changes):

Expand All @@ -33,8 +34,42 @@ git remote -v | head -1

# 3. Check for uncommitted work
git status --short

# 4. Check for remote updates (parallel session safety)
git fetch origin
git log --oneline HEAD..origin/$(git branch --show-current) 2>/dev/null
```

**Parallel Session Safety**:

When running multiple OpenCode sessions on the same repo:

| Situation | Action |
|-----------|--------|
| Remote has new commits | Pull/rebase before continuing |
| Uncommitted local changes | Stash or commit before switching |
| Different session on same branch | Coordinate or use separate branches |
| Starting new work | Always create a new branch first |

**Session-Branch Tracking**:

OpenCode auto-generates session titles from the first prompt. To sync session names with branches:

| Command | Purpose |
|---------|---------|
| `/sync-branch` | Rename session to match current git branch |
| `/rename feature/xyz` | Rename session to any title |

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For clarity, the command in the documentation should be represented generically using a placeholder, rather than a specific example. This helps users understand that feature/xyz is a placeholder for a value they need to provide.

Suggested change
| `/rename feature/xyz` | Rename session to any title |
| `/rename <new-title>` | Rename session to any title |

| `/sessions` (Ctrl+x l) | List all sessions by name |

| Workflow | How to Track |
|----------|--------------|
| **New session, known work** | Start with: `opencode --title "feature/my-feature"` |
| **Existing session, new branch** | Run `/sync-branch` after creating branch |
| **Multiple sessions** | Each session named after its branch |
| **Resume work** | `opencode -c` continues last session, or `-s <id>` for specific |

**Best Practice**: After creating a branch, run `/sync-branch` to rename the session to match.

**Decision Tree**:

| Situation | Action |
Expand Down
52 changes: 52 additions & 0 deletions .agent/workflows/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,58 @@ Before running the release command:
The release script will **refuse to release** if there are uncommitted changes.
This prevents accidentally releasing without your session's work.

## Merging Work Branch to Main

Before releasing, merge your work branch to main (or create PR/MR if collaborating):

### Direct Merge (Solo Work)

```bash
# 1. Ensure branch is up to date
git checkout {your-branch}
git fetch origin
git rebase origin/main # or merge

# 2. Switch to main and merge
git checkout main
git pull origin main
git merge --no-ff {your-branch} -m "Merge {your-branch} into main"

# 3. Push merged main
git push origin main

# 4. Delete branch after merge
git branch -d {your-branch}
git push origin --delete {your-branch}
```

### PR/MR Workflow (Collaborative)

When working with others or requiring review:

```bash
# 1. Push branch
git push -u origin {your-branch}

# 2. Create PR/MR
gh pr create --fill --base main # GitHub
glab mr create --fill --target-branch main # GitLab

# 3. After approval and merge, continue with release
git checkout main
git pull origin main
```

### Decision Tree

| Situation | Action |
|-----------|--------|
| Solo work, simple changes | Direct merge to main |
| Team collaboration | Create PR/MR for review |
| Multiple branches to release | Merge each to main, then release |
| Hotfix on production | Use `hotfix/` branch, merge to main + release |
| Parallel sessions, same feature | Coordinate via PR to avoid conflicts |

## Release Workflow Overview

The release script handles everything automatically:
Expand Down
7 changes: 7 additions & 0 deletions .opencode/command/rename.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
description: Rename this session
---

Rename this session to: $ARGUMENTS

Use the session-rename tool to update the session title.
5 changes: 5 additions & 0 deletions .opencode/command/sync-branch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
description: Sync session title with current git branch
---

Use the session-rename_sync_branch tool to rename this session to match the current git branch name.
78 changes: 78 additions & 0 deletions .opencode/tool/session-rename.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { tool } from "@opencode-ai/plugin"

export default tool({
description: "Rename the current session to a new title. Use this after creating a git branch to sync the session name with the branch name.",
args: {
title: tool.schema.string().describe("New title for the session (e.g., branch name like 'feature/my-feature')"),
},
async execute(args, context) {
const { sessionID } = context
const { title } = args

// Call the OpenCode API to update the session
// The server runs on localhost:4096 by default
const port = process.env.OPENCODE_PORT || "4096"
const baseUrl = `http://localhost:${port}`

try {
const response = await fetch(`${baseUrl}/session/${sessionID}`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ title }),
})

if (!response.ok) {
const error = await response.text()
return `Failed to rename session: ${error}`
}

const session = await response.json()
return `Session renamed to: ${session.title || title}`
} catch (error) {
return `Error renaming session: ${error instanceof Error ? error.message : String(error)}`
}
},
})

// Also export a tool that syncs with the current git branch
export const sync_branch = tool({
description: "Rename the current session to match the current git branch name. Call this after creating or switching branches.",
args: {},
async execute(_args, context) {
const { sessionID } = context

// Get current branch name
const branchResult = await Bun.$`git branch --show-current`.text()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bun.$\git branch --show-current`can throw (e.g., not a git repo / detached HEAD), which would bypass the laterif (!branch)message; consider catching the command failure (similar to howgithub-release.tsuses.catch(...)) so /sync-branch` degrades gracefully.

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎

const branch = branchResult.trim()

if (!branch) {
return "Not in a git repository or no branch checked out"
}

// Call the OpenCode API to update the session
const port = process.env.OPENCODE_PORT || "4096"
const baseUrl = `http://localhost:${port}`

try {
const response = await fetch(`${baseUrl}/session/${sessionID}`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ title: branch }),
})

if (!response.ok) {
const error = await response.text()
return `Failed to sync session with branch: ${error}`
}

const session = await response.json()
return `Session synced with branch: ${session.title || branch}`
} catch (error) {
return `Error syncing session: ${error instanceof Error ? error.message : String(error)}`
}
},
})
Comment on lines +1 to +78

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This file has two main areas for improvement:

  1. Unhandled Exception: The Bun.$ command at line 47 can throw an exception if the git command fails (e.g., not in a git repository). This exception is not currently caught, which would crash the tool. The try...catch block should be extended to cover this call.

  2. Code Duplication: The logic for making the API call to rename the session is duplicated in both the default tool and the sync_branch tool. This can be extracted into a shared helper function to improve maintainability and reduce redundancy.

The suggested change below addresses both points by creating a renameSession helper and ensuring all fallible operations are within try...catch blocks.

import { tool } from "@opencode-ai/plugin"

async function renameSession(sessionID: string, title: string): Promise<string> {
  // Call the OpenCode API to update the session
  // The server runs on localhost:4096 by default
  const port = process.env.OPENCODE_PORT || "4096"
  const baseUrl = `http://localhost:${port}`
  
  const response = await fetch(`${baseUrl}/session/${sessionID}`, {
    method: "PATCH",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ title }),
  })
  
  if (!response.ok) {
    const error = await response.text()
    // Throwing an error to be caught by the caller
    throw new Error(error)
  }
  
  const session = await response.json()
  return session.title || title
}

export default tool({
  description: "Rename the current session to a new title. Use this after creating a git branch to sync the session name with the branch name.",
  args: {
    title: tool.schema.string().describe("New title for the session (e.g., branch name like 'feature/my-feature')"),
  },
  async execute(args, context) {
    const { sessionID } = context
    const { title } = args
    
    try {
      const newTitle = await renameSession(sessionID, title)
      return `Session renamed to: ${newTitle}`
    } catch (error) {
      return `Failed to rename session: ${error instanceof Error ? error.message : String(error)}`
    }
  },
})

// Also export a tool that syncs with the current git branch
export const sync_branch = tool({
  description: "Rename the current session to match the current git branch name. Call this after creating or switching branches.",
  args: {},
  async execute(_args, context) {
    const { sessionID } = context
    
    try {
      // Get current branch name
      const branchResult = await Bun.$`git branch --show-current`.text()
      const branch = branchResult.trim()
      
      if (!branch) {
        return "Not in a git repository or no branch checked out"
      }
      
      const newTitle = await renameSession(sessionID, branch)
      return `Session synced with branch: ${newTitle}`
    } catch (error) {
      return `Error syncing session: ${error instanceof Error ? error.message : String(error)}`
    }
  },
})