diff --git a/ui/components/reposection/commands.go b/ui/components/reposection/commands.go
index 94de9e91..46218ae3 100644
--- a/ui/components/reposection/commands.go
+++ b/ui/components/reposection/commands.go
@@ -7,6 +7,7 @@ import (
 
 	gitm "github.com/aymanbagabas/git-module"
 	tea "github.com/charmbracelet/bubbletea"
+	"github.com/charmbracelet/log"
 
 	"github.com/dlvhdr/gh-dash/v4/data"
 	"github.com/dlvhdr/gh-dash/v4/git"
@@ -76,24 +77,49 @@ func (m *Model) fastForward() (tea.Cmd, error) {
 	}), nil
 }
 
-func (m *Model) push() (tea.Cmd, error) {
+type pushOptions struct {
+	force bool
+}
+
+func (m *Model) push(opts pushOptions) (tea.Cmd, error) {
 	b := m.getCurrBranch()
 
 	taskId := fmt.Sprintf("push_%s_%d", b.Data.Name, time.Now().Unix())
+	withForceText := func() string {
+		if opts.force {
+			return " with force"
+		}
+		return ""
+	}
 	task := context.Task{
 		Id:           taskId,
-		StartText:    fmt.Sprintf("Pushing branch %s", b.Data.Name),
-		FinishedText: fmt.Sprintf("Branch %s has been pushed", b.Data.Name),
+		StartText:    fmt.Sprintf("Pushing branch %s%s", b.Data.Name, withForceText()),
+		FinishedText: fmt.Sprintf("Branch %s has been pushed%s", b.Data.Name, withForceText()),
 		State:        context.TaskStart,
 		Error:        nil,
 	}
 	startCmd := m.Ctx.StartTask(task)
 	return tea.Batch(startCmd, func() tea.Msg {
 		var err error
+		args := []string{}
+		if opts.force {
+			args = append(args, "--force")
+		}
 		if len(b.Data.Remotes) == 0 {
-			err = gitm.Push(*m.Ctx.RepoPath, "origin", b.Data.Name, gitm.PushOptions{CommandOptions: gitm.CommandOptions{Args: []string{"--set-upstream"}}})
+			args = append(args, "--set-upstream")
+			err = gitm.Push(
+				*m.Ctx.RepoPath,
+				"origin",
+				b.Data.Name,
+				gitm.PushOptions{CommandOptions: gitm.CommandOptions{Args: args}},
+			)
 		} else {
-			err = gitm.Push(*m.Ctx.RepoPath, b.Data.Remotes[0], b.Data.Name)
+			err = gitm.Push(
+				*m.Ctx.RepoPath,
+				b.Data.Remotes[0],
+				b.Data.Name,
+				gitm.PushOptions{CommandOptions: gitm.CommandOptions{Args: args}},
+			)
 		}
 		if err != nil {
 			return constants.TaskFinishedMsg{TaskId: taskId, Err: err}
@@ -248,6 +274,49 @@ func (m *Model) fetchPRsCmd() tea.Cmd {
 	})
 }
 
+func (m *Model) fetchPRCmd(branch string) []tea.Cmd {
+	prsTaskId := fmt.Sprintf("fetching_pr_for_branch_%s_%d", branch, time.Now().Unix())
+	task := context.Task{
+		Id:           prsTaskId,
+		StartText:    fmt.Sprintf("Fetching PR for branch %s", branch),
+		FinishedText: "PR fetched",
+		State:        context.TaskStart,
+		Error:        nil,
+	}
+	startCmd := m.Ctx.StartTask(task)
+	return []tea.Cmd{startCmd, func() tea.Msg {
+		res, err := data.FetchPullRequests(fmt.Sprintf("author:@me repo:%s head:%s", git.GetRepoShortName(*m.Ctx.RepoUrl), branch), 1, nil)
+		log.Debug("Fetching PRs", "res", res)
+		if err != nil {
+			return constants.TaskFinishedMsg{
+				SectionId:   0,
+				SectionType: SectionType,
+				TaskId:      prsTaskId,
+				Err:         err,
+			}
+		}
+
+		if len(res.Prs) != 1 {
+			return constants.TaskFinishedMsg{
+				SectionId:   0,
+				SectionType: SectionType,
+				TaskId:      prsTaskId,
+				Err:         fmt.Errorf("expected 1 PR, got %d", len(res.Prs)),
+			}
+		}
+
+		return constants.TaskFinishedMsg{
+			SectionId:   0,
+			SectionType: SectionType,
+			TaskId:      prsTaskId,
+			Msg: tasks.UpdateBranchMsg{
+				Name:  branch,
+				NewPr: &res.Prs[0],
+			},
+		}
+	}}
+}
+
 type RefreshBranchesMsg struct {
 	id   int
 	time time.Time
diff --git a/ui/components/reposection/reposection.go b/ui/components/reposection/reposection.go
index f0cc97b1..bfeabeae 100644
--- a/ui/components/reposection/reposection.go
+++ b/ui/components/reposection/reposection.go
@@ -104,11 +104,14 @@ func (m *Model) Update(msg tea.Msg) (section.Section, tea.Cmd) {
 			case msg.Type == tea.KeyEnter:
 				input := m.PromptConfirmationBox.Value()
 				action := m.GetPromptConfirmationAction()
+				branch := m.getCurrBranch().Data.Name
+				sid := tasks.SectionIdentifer{Id: m.Id, Type: SectionType}
 				if action == "new" {
 					cmd = m.newBranch(input)
+				} else if action == "create_pr" {
+					cmd = tasks.CreatePR(m.Ctx, sid, branch, input)
 				} else {
-					pr := findPRForRef(m.Prs, m.getCurrBranch().Data.Name)
-					sid := tasks.SectionIdentifer{Id: m.Id, Type: SectionType}
+					pr := findPRForRef(m.Prs, branch)
 					if input == "Y" || input == "y" {
 						switch action {
 						case "delete":
@@ -142,7 +145,12 @@ func (m *Model) Update(msg tea.Msg) (section.Section, tea.Cmd) {
 			}
 
 		case key.Matches(msg, keys.BranchKeys.Push):
-			cmd, err = m.push()
+			cmd, err = m.push(pushOptions{force: false})
+			if err != nil {
+				m.Ctx.Error = err
+			}
+		case key.Matches(msg, keys.BranchKeys.ForcePush):
+			cmd, err = m.push(pushOptions{force: true})
 			if err != nil {
 				m.Ctx.Error = err
 			}
@@ -154,6 +162,14 @@ func (m *Model) Update(msg tea.Msg) (section.Section, tea.Cmd) {
 
 		}
 
+	case tasks.UpdateBranchMsg:
+		if msg.IsCreated != nil && *msg.IsCreated {
+			cmds = append(cmds, m.fetchPRCmd(msg.Name)...)
+		}
+		if msg.NewPr != nil {
+			m.Prs = append(m.Prs, *msg.NewPr)
+		}
+
 	case repoMsg:
 		m.repo = msg.repo
 		m.Table.SetIsLoading(false)
@@ -193,7 +209,6 @@ func (m *Model) Update(msg tea.Msg) (section.Section, tea.Cmd) {
 
 	m.Table.SetRows(m.BuildRows())
 	table, tableCmd := m.Table.Update(msg)
-	cmds = append(cmds, tableCmd)
 	m.Table = table
 	cmds = append(cmds, tableCmd)
 
diff --git a/ui/components/section/section.go b/ui/components/section/section.go
index 1fd22131..c601fd67 100644
--- a/ui/components/section/section.go
+++ b/ui/components/section/section.go
@@ -355,6 +355,8 @@ func (m *BaseModel) GetPromptConfirmation() string {
 			prompt = "Are you sure you want to delete this branch? (Y/n) "
 		case m.PromptConfirmationAction == "new" && m.Ctx.View == config.RepoView:
 			prompt = "Enter branch name: "
+		case m.PromptConfirmationAction == "create_pr" && m.Ctx.View == config.RepoView:
+			prompt = "Enter PR title: "
 		}
 
 		m.PromptConfirmationBox.SetPrompt(prompt)
diff --git a/ui/components/tasks/pr.go b/ui/components/tasks/pr.go
index 0f75cb60..cff8f477 100644
--- a/ui/components/tasks/pr.go
+++ b/ui/components/tasks/pr.go
@@ -3,8 +3,10 @@ package tasks
 import (
 	"fmt"
 	"os/exec"
+	"strings"
 
 	tea "github.com/charmbracelet/bubbletea"
+	"github.com/charmbracelet/log"
 
 	"github.com/dlvhdr/gh-dash/v4/data"
 	"github.com/dlvhdr/gh-dash/v4/ui/constants"
@@ -27,6 +29,12 @@ type UpdatePRMsg struct {
 	RemovedAssignees *data.Assignees
 }
 
+type UpdateBranchMsg struct {
+	Name      string
+	IsCreated *bool
+	NewPr     *data.PullRequestData
+}
+
 func buildTaskId(prefix string, prNumber int) string {
 	return fmt.Sprintf("%s_%d", prefix, prNumber)
 }
@@ -37,7 +45,7 @@ type GitHubTask struct {
 	Section      SectionIdentifer
 	StartText    string
 	FinishedText string
-	Msg          func(c *exec.Cmd, err error) UpdatePRMsg
+	Msg          func(c *exec.Cmd, err error) tea.Msg
 }
 
 func fireTask(ctx *context.ProgramContext, task GitHubTask) tea.Cmd {
@@ -51,6 +59,7 @@ func fireTask(ctx *context.ProgramContext, task GitHubTask) tea.Cmd {
 
 	startCmd := ctx.StartTask(start)
 	return tea.Batch(startCmd, func() tea.Msg {
+		log.Debug("Running task", "cmd", "gh "+strings.Join(task.Args, " "))
 		c := exec.Command("gh", task.Args...)
 
 		err := c.Run()
@@ -78,7 +87,7 @@ func OpenBranchPR(ctx *context.ProgramContext, section SectionIdentifer, branch
 		Section:      section,
 		StartText:    fmt.Sprintf("Opening PR for branch %s", branch),
 		FinishedText: fmt.Sprintf("PR for branch %s has been opened", branch),
-		Msg: func(c *exec.Cmd, err error) UpdatePRMsg {
+		Msg: func(c *exec.Cmd, err error) tea.Msg {
 			return UpdatePRMsg{}
 		},
 	})
@@ -98,7 +107,7 @@ func ReopenPR(ctx *context.ProgramContext, section SectionIdentifer, pr data.Row
 		Section:      section,
 		StartText:    fmt.Sprintf("Reopening PR #%d", prNumber),
 		FinishedText: fmt.Sprintf("PR #%d has been reopened", prNumber),
-		Msg: func(c *exec.Cmd, err error) UpdatePRMsg {
+		Msg: func(c *exec.Cmd, err error) tea.Msg {
 			return UpdatePRMsg{
 				PrNumber: prNumber,
 				IsClosed: utils.BoolPtr(false),
@@ -121,7 +130,7 @@ func ClosePR(ctx *context.ProgramContext, section SectionIdentifer, pr data.RowD
 		Section:      section,
 		StartText:    fmt.Sprintf("Closing PR #%d", prNumber),
 		FinishedText: fmt.Sprintf("PR #%d has been closed", prNumber),
-		Msg: func(c *exec.Cmd, err error) UpdatePRMsg {
+		Msg: func(c *exec.Cmd, err error) tea.Msg {
 			return UpdatePRMsg{
 				PrNumber: prNumber,
 				IsClosed: utils.BoolPtr(true),
@@ -144,7 +153,7 @@ func PRReady(ctx *context.ProgramContext, section SectionIdentifer, pr data.RowD
 		Section:      section,
 		StartText:    fmt.Sprintf("Marking PR #%d as ready for review", prNumber),
 		FinishedText: fmt.Sprintf("PR #%d has been marked as ready for review", prNumber),
-		Msg: func(c *exec.Cmd, err error) UpdatePRMsg {
+		Msg: func(c *exec.Cmd, err error) tea.Msg {
 			return UpdatePRMsg{
 				PrNumber:       prNumber,
 				ReadyForReview: utils.BoolPtr(true),
@@ -192,3 +201,40 @@ func MergePR(ctx *context.ProgramContext, section SectionIdentifer, pr data.RowD
 		}
 	}))
 }
+
+func CreatePR(ctx *context.ProgramContext, section SectionIdentifer, branchName string, title string) tea.Cmd {
+	c := exec.Command(
+		"gh",
+		"pr",
+		"create",
+		"--title",
+		title,
+		"-R",
+		*ctx.RepoUrl,
+	)
+
+	taskId := fmt.Sprintf("create_pr_%s", title)
+	task := context.Task{
+		Id:           taskId,
+		StartText:    fmt.Sprintf(`Creating PR "%s"`, title),
+		FinishedText: fmt.Sprintf(`PR "%s" has been created`, title),
+		State:        context.TaskStart,
+		Error:        nil,
+	}
+	startCmd := ctx.StartTask(task)
+
+	return tea.Batch(startCmd, tea.ExecProcess(c, func(err error) tea.Msg {
+		isCreated := false
+		if err == nil && c.ProcessState.ExitCode() == 0 {
+			isCreated = true
+		}
+
+		return constants.TaskFinishedMsg{
+			SectionId:   section.Id,
+			SectionType: section.Type,
+			TaskId:      taskId,
+			Err:         nil,
+			Msg:         UpdateBranchMsg{Name: branchName, IsCreated: &isCreated},
+		}
+	}))
+}
diff --git a/ui/keys/branchKeys.go b/ui/keys/branchKeys.go
index bfe244a3..4d313bd0 100644
--- a/ui/keys/branchKeys.go
+++ b/ui/keys/branchKeys.go
@@ -12,8 +12,10 @@ import (
 type BranchKeyMap struct {
 	Checkout    key.Binding
 	New         key.Binding
+	CreatePr    key.Binding
 	FastForward key.Binding
 	Push        key.Binding
+	ForcePush   key.Binding
 	Delete      key.Binding
 	ViewPRs     key.Binding
 }
@@ -27,6 +29,10 @@ var BranchKeys = BranchKeyMap{
 		key.WithKeys("n"),
 		key.WithHelp("n", "new"),
 	),
+	CreatePr: key.NewBinding(
+		key.WithKeys("O"),
+		key.WithHelp("O", "create PR"),
+	),
 	FastForward: key.NewBinding(
 		key.WithKeys("f"),
 		key.WithHelp("f", "fast-forward"),
@@ -35,6 +41,10 @@ var BranchKeys = BranchKeyMap{
 		key.WithKeys("P"),
 		key.WithHelp("P", "push"),
 	),
+	ForcePush: key.NewBinding(
+		key.WithKeys("F"),
+		key.WithHelp("F", "force-push"),
+	),
 	Delete: key.NewBinding(
 		key.WithKeys("d", "backspace"),
 		key.WithHelp("d/backspace", "delete"),
@@ -50,7 +60,9 @@ func BranchFullHelp() []key.Binding {
 		BranchKeys.Checkout,
 		BranchKeys.FastForward,
 		BranchKeys.Push,
+		BranchKeys.ForcePush,
 		BranchKeys.New,
+		BranchKeys.CreatePr,
 		BranchKeys.Delete,
 		BranchKeys.ViewPRs,
 	}
@@ -69,10 +81,14 @@ func rebindBranchKeys(keys []config.Keybinding) error {
 		switch branchKey.Builtin {
 		case "new":
 			key = &BranchKeys.New
+		case "createPr":
+			key = &BranchKeys.CreatePr
 		case "delete":
 			key = &BranchKeys.Delete
 		case "push":
 			key = &BranchKeys.Push
+		case "forcePush":
+			key = &BranchKeys.ForcePush
 		case "fastForward":
 			key = &BranchKeys.FastForward
 		case "checkout":
diff --git a/ui/ui.go b/ui/ui.go
index 1448aa9a..7ac2832b 100644
--- a/ui/ui.go
+++ b/ui/ui.go
@@ -305,6 +305,13 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 				}
 				return m, cmd
 
+			case key.Matches(msg, keys.BranchKeys.CreatePr):
+				if currSection != nil {
+					currSection.SetPromptConfirmationAction("create_pr")
+					cmd = currSection.SetIsPromptConfirmationShown(true)
+				}
+				return m, cmd
+
 			case key.Matches(msg, keys.BranchKeys.ViewPRs):
 				m.ctx.View = m.switchSelectedView()
 				m.syncMainContentWidth()
@@ -495,11 +502,14 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 			now := time.Now()
 			task.FinishedTime = &now
 			m.tasks[msg.TaskId] = task
-			cmd = tea.Tick(2*time.Second, func(t time.Time) tea.Msg {
+			clear := tea.Tick(2*time.Second, func(t time.Time) tea.Msg {
 				return constants.ClearTaskMsg{TaskId: msg.TaskId}
 			})
+			cmds = append(cmds, clear)
+
+			scmd := m.updateSection(msg.SectionId, msg.SectionType, msg.Msg)
+			cmds = append(cmds, scmd)
 
-			m.updateSection(msg.SectionId, msg.SectionType, msg.Msg)
 			m.syncSidebar()
 		}
 
