duckhunt-agent-config
ChatGPTReads what duckhunt agents may do for this user, and where. Inside an agent run, self is the run's own effective policy: tier, effective profile and its stored ceiling, the lock that forces read and the layer that set it, kit (shell, aws, file writes, memory, web, mcp tools), timeout, whether another turn would be accepted and whether the daily turn cap is reached. launch previews a new conversation from this workspace (or workspaceId) and repo: whether it can be launched and why not, default profile and its lock, timeout, daily caps with usage (max null = no cap set; ruleRuns = investigations launched by the user's automation rules against the daily limit the user sets, or the instance cap when it is stricter), and the machines that would run it. Also the instance limits for this user, the user's MCP behaviour settings, their machines (name, online, paused, accepts, capabilities, slots in use) and the repo keys they can use (provider, mode, default profile, mapped machines with health, linked workspaces). Each policy value carries the layer that decided it (instance, person, workspace, repo, runner, run). Use it before proposing or launching agent work. Read-only: the user changes agent policy in duckhunt settings, never over MCP.
duckhunt-agent-investigate
ChatGPTEnqueues an investigation agent run on any entry (alert, ticket, PR, email…; the prompt adapts to its category): the duckhunt-runner daemon of the user, on their machine, claims it and launches claude code as a read-only conversation in an isolated worktree of the repo (read-only shell; read-only aws cli only for the entry account the machine maps; no web) with the duckhunt mcp; the verdict is stored in the run conversation and can be sent via push. Optional repo (ws/slug) and branch; without repo it is resolved from the entry (pr → its repo; attached target → target_repo; nightwatch app → its repo). Returns the reference of the enqueued run (r#N, to follow it with duckhunt-agent-run-get) or the skip reason (active_run: another copy of the same item is already being investigated, e.g. the same alert in another workspace; cooldown; daily_cap; daily_turn_cap). The user gets a launch alert on their devices for every run enqueued here.
duckhunt-agent-run-get
ChatGPTReads a whole agent run by its r#N reference: status, investigated entry, cost, and the full thread (the conversation between the agent and the user, the questions with their answer and the chain of continuations) and the similar earlier runs it was shown when it was launched (similarRuns). Use it when the user mentions a run in the conversation ("what happened with r#87?"): it is what is shown in /agents.
duckhunt-agent-run-list
ChatGPTAgent runs of the user in the workspace of the token, most recent first: r#N reference, status, investigated entry, the target it was launched from and verdict in one sentence. Optional filters by status (several), source, provider of the entry and target (runs launched from it or on its attached entries, in any workspace). allWorkspaces=true lists the runs of ALL workspaces of the user. To read the whole conversation of one, duckhunt-agent-run-get.
duckhunt-attachment-add
ChatGPTUploads base64 content (dataBase64, also accepts a data-url data:...;base64,...) as an attachment of a task. ONLY for small content that you generate right here (a few KB: a note, a short diff). If the file is already on disk or weighs more than ~64 KB use duckhunt-attachment-upload-ticket: base64 goes through the conversation and costs ~1.4 characters per byte (a 100 KB png is ~137,000 characters, and they are paid twice if you also generate it with base64 in the terminal). 10 MB limit per file and subject to the storage quota of the task owner. Requires write permission on the task. contentType is optional: if omitted it is inferred from the filename extension (it matters so attachment-read later renders it as image/text). Attachments appear in duckhunt-attachment-list and in attachments of duckhunt-target-get. Returns the created metadata {id, filename, contentType, sizeBytes, url}.
duckhunt-attachment-delete
ChatGPTDeletes an attachment by its id (the one from duckhunt-attachment-list): the metadata row + the blob. Requires write permission on the owning task. Idempotent on retries. Returns {ok, targetId}; error if it does not exist or without permission.
duckhunt-attachment-list
ChatGPTLists the attachments of a task: [{id, filename, contentType, sizeBytes, createdAt, url}]. It is the cheap way to find the id that duckhunt-attachment-read/delete need, instead of requesting the whole detail with duckhunt-target-get. [] if the task has no attachments. Does not return content.
duckhunt-attachment-read
ChatGPTReads the content of an attachment by its id (the one from duckhunt-attachment-list, or from attachments in duckhunt-target-get). Images are returned as an image block (directly visible); text files as plain text; everything else as a base64 binary resource. Use it to inspect a bug screenshot, a log or a file the user attached to the task. Requires read access to the owning task.
duckhunt-attachment-upload-ticket
ChatGPTTHIS is the way to attach a file that ALREADY EXISTS ON DISK (a screenshot, a log, a pdf, a binary): returns a single-use upload url and you upload the file with curl, without its bytes going through the conversation. Do NOT read the file or convert it to base64; with the url you only copy the command. Returns {uploadUrl, expiresInS, maxBytes, curl}: run curl (the field contains the ready command, just replace the path) and the 201 response gives you the metadata of the created attachment. The url expires in 5 minutes, works for ONE upload and is not valid for another file or another task: request one ticket per file. 10 MB limit and subject to the owner quota; requires write permission on the task (checked already when issuing the ticket). contentType is optional: if omitted it is inferred from the filename extension.
duckhunt-automation-create-archive-tasks
ChatGPTCreates one automation rule to archive tasks. Archives the subject tasks. Available on target transitions or schedules with scan=targets. This call saves the rule; it does not execute the action immediately.
duckhunt-automation-create-attach-entry
ChatGPTCreates one automation rule to attach entries. Attaches the matching entry to an owned task. Supply exactly one of targetId or match=jira_key. This call saves the rule; it does not execute the action immediately.
duckhunt-automation-create-create-task
ChatGPTCreates one automation rule to create tasks. Creates a task when the entry or schedule trigger fires. attachTrigger also links the triggering entry. This call saves the rule; it does not execute the action immediately.
duckhunt-automation-create-investigate
ChatGPTCreates one automation rule to investigate entries. Queues a read-only investigation of the triggering entry on the user runner using its type template. Saved disabled; the user enables it in Duckhunt. Posting the result to Jira is not supported by this tool. This call saves the rule; it does not execute the action immediately.
duckhunt-automation-create-notify
ChatGPTCreates one automation rule to send notifications. Sends an in-app/push notification to the rule owner about the triggering entry. Requires an entry trigger. This call saves the rule; it does not execute the action immediately.
duckhunt-automation-create-run-prompt
ChatGPTCreates one automation rule to run prompts. Queues the supplied prompt on the user runner with the read repository profile. The agent may change Duckhunt data through its allowed tools but cannot edit repository code. Anchored to the triggering entry/task, each scanned task, or no item on a schedule without scan. Saved disabled; the user enables it in Duckhunt. This call saves the rule; it does not execute the action immediately.
duckhunt-automation-create-suppress-event
ChatGPTCreates one automation rule to suppress inbox events. Discards the matching inbox event and prevents its notification. Requires trigger=entry and triggerConfig.on=notified. This call saves the rule; it does not execute the action immediately.
duckhunt-automation-create-update-tasks
ChatGPTCreates one automation rule to update tasks. Changes status, type, priority or labels of the subject tasks. Supply at least one change. A schedule requires scan=targets. This call saves the rule; it does not execute the action immediately.
duckhunt-automation-delete
ChatGPTDeletes an automation rule you own (and its run log).
duckhunt-automation-list
ChatGPTReads saved automation rules owned by the user in the active workspace, including global rules. Returns their configuration and enabled/expired state. Does not execute, create, modify or enable rules. Each supported automation action has separate create/update tools with its full schema in tools/list. Use duckhunt-automation-runs to read execution history.
duckhunt-automation-runs
ChatGPTReads the latest 50 persisted execution records of one owned automation rule, newest first. Does not run or retry the rule.
duckhunt-automation-update-archive-tasks
ChatGPTUpdates one owned automation rule whose only action is to archive tasks. Archives the subject tasks. Available on target transitions or schedules with scan=targets. Omitted fields are preserved; action, triggerConfig and conditions replace their previous values when supplied. Rejects rules with a different action or multiple actions; edit those in Duckhunt settings. This call does not execute the action immediately.
duckhunt-automation-update-attach-entry
ChatGPTUpdates one owned automation rule whose only action is to attach entries. Attaches the matching entry to an owned task. Supply exactly one of targetId or match=jira_key. Omitted fields are preserved; action, triggerConfig and conditions replace their previous values when supplied. Rejects rules with a different action or multiple actions; edit those in Duckhunt settings. This call does not execute the action immediately.
duckhunt-automation-update-create-task
ChatGPTUpdates one owned automation rule whose only action is to create tasks. Creates a task when the entry or schedule trigger fires. attachTrigger also links the triggering entry. Omitted fields are preserved; action, triggerConfig and conditions replace their previous values when supplied. Rejects rules with a different action or multiple actions; edit those in Duckhunt settings. This call does not execute the action immediately.
duckhunt-automation-update-investigate
ChatGPTUpdates one owned automation rule whose only action is to investigate entries. Queues a read-only investigation of the triggering entry on the user runner using its type template. Saved disabled; the user enables it in Duckhunt. Posting the result to Jira is not supported by this tool. Omitted fields are preserved; action, triggerConfig and conditions replace their previous values when supplied. Rejects rules with a different action or multiple actions; edit those in Duckhunt settings. This call does not execute the action immediately.
duckhunt-automation-update-notify
ChatGPTUpdates one owned automation rule whose only action is to send notifications. Sends an in-app/push notification to the rule owner about the triggering entry. Requires an entry trigger. Omitted fields are preserved; action, triggerConfig and conditions replace their previous values when supplied. Rejects rules with a different action or multiple actions; edit those in Duckhunt settings. This call does not execute the action immediately.
duckhunt-automation-update-run-prompt
ChatGPTUpdates one owned automation rule whose only action is to run prompts. Queues the supplied prompt on the user runner with the read repository profile. The agent may change Duckhunt data through its allowed tools but cannot edit repository code. Anchored to the triggering entry/task, each scanned task, or no item on a schedule without scan. Saved disabled; the user enables it in Duckhunt. Omitted fields are preserved; action, triggerConfig and conditions replace their previous values when supplied. Rejects rules with a different action or multiple actions; edit those in Duckhunt settings. This call does not execute the action immediately.
duckhunt-automation-update-suppress-event
ChatGPTUpdates one owned automation rule whose only action is to suppress inbox events. Discards the matching inbox event and prevents its notification. Requires trigger=entry and triggerConfig.on=notified. Omitted fields are preserved; action, triggerConfig and conditions replace their previous values when supplied. Rejects rules with a different action or multiple actions; edit those in Duckhunt settings. This call does not execute the action immediately.
duckhunt-automation-update-update-tasks
ChatGPTUpdates one owned automation rule whose only action is to update tasks. Changes status, type, priority or labels of the subject tasks. Supply at least one change. A schedule requires scan=targets. Omitted fields are preserved; action, triggerConfig and conditions replace their previous values when supplied. Rejects rules with a different action or multiple actions; edit those in Duckhunt settings. This call does not execute the action immediately.
duckhunt-bitbucket-pr-tasks
ChatGPTTasks of the pr (checklist items with state UNRESOLVED|RESOLVED). A single page.
duckhunt-bitbucket-task-resolve
ChatGPTResolves (or reopens with resolved=false) a checklist task of a bitbucket pr. taskId comes from duckhunt-bitbucket-pr-tasks. Closes the loop of addressing review feedback.
duckhunt-brief
ChatGPTSingle-call orientation: in_progress tasks with their latest work note (handoff from the previous session) and blocked flag, what is due in the next 7 days, the number of unseen items in the inbox, and concurrentTasks (tasks that your OTHER agent connections are working RIGHT NOW: once you work a task, only the same task or tasks sharing one of its repos; before that, the ones in this workspace that declare repos, each with its repos — coordinate only if one is the repo you work in). Start here before target-list/inbox.
duckhunt-calendar-upcoming
ChatGPTUpcoming agenda: calendar events (google calendar) of the workspace + targets with a due date, from today up to days days ahead (default 7, max 30).
duckhunt-code-commits
ChatGPTLists the commits of a code review entry (pr/mr): hash, message, author and date, newest first. Generic (bitbucket today). Useful to understand the scope of a pr before reviewing or commenting on it.
duckhunt-code-diff
ChatGPTUnified diff (raw text) of a code review entry (pr/mr), capped at 200KB. Generic (bitbucket today). The basis for reviewing the changes and leaving comments with duckhunt-entry-comment.
duckhunt-daily-generate
ChatGPTGenerates (or regenerates) the daily note for a date (YYYY-MM-DD, default: today) from the kanban transitions, according to the config of the active workspace (in per-workspace scope there is one note per workspace). Stored as a duckhunt note (read or edit it with duckhunt-user-note-get/update using the returned noteId). Preserves user edits below the marker.
duckhunt-daily-list
ChatGPTLists the user's daily notes (stored as duckhunt notes, one per day, or per workspace and day in per-workspace scope), newest first
duckhunt-daily-preview
ChatGPTReturns the markdown the daily note would generate for a date (YYYY-MM-DD, default: today) without writing anything. Respects the config of the active workspace (global vs per-workspace scope, filters, sections).
duckhunt-entry-claim
ChatGPTCreates a new task with this entry attached. Returns the targetId.
duckhunt-entry-delete
ChatGPTDeletes an entry you own: detaches it from its targets and removes its local data (extensions, comments, events, custom fields). Its agent conversations are kept (they move to a deleted-entry placeholder and stay in /agents). Hard delete WITHOUT tombstone: if the entry is still alive in its source (a jira issue still assigned, an email, a notion page still shared), the poller may re-ingest it later. Use it to clean up stale or orphaned entries, not to archive work in progress (for that, move/archive the target).
duckhunt-entry-field-options
ChatGPTSelectable options for a field in its source. Without transitionId: editable field of the entry (assignable users, open sprints, project versions, labels, priorities, components; duedate has no options, use YYYY-MM-DD in set-field). With transitionId: field on the screen of THAT transition (field = the id returned by duckhunt-entry-list-transitions, e.g. resolution or customfield_10034), useful when its catalog does not fit entirely in the response (user directories). q filters. Supported according to the provider capabilities (jira today).
duckhunt-entry-file-list
ChatGPTLists the files hanging from the SOURCE of an entry: attachments of an email (including the images pasted in the body, inline: true), attachments of a jira ticket or files of a slack message. They are not stored in duckhunt: they live in the source and are read on-demand. Returns [{ref, filename, contentType, sizeBytes, inline, from}]; ref is opaque and is what duckhunt-entry-file-read/save accept. [] if the source has no files. Use it when the ticket or the email mention a screenshot, a log or a pdf you need to look at.
duckhunt-entry-file-read
ChatGPTReads a file from the source of an entry by its ref (from duckhunt-entry-file-list). It is downloaded from the mailbox/jira/slack at that moment, so it requires the connection to still be alive. Images are returned as an image block (you can SEE THEM: bug screenshots, mockups, charts), text files as plain text and everything else as a base64 binary resource. Maximum 25 MB. If the file must stay in the task, use duckhunt-entry-file-save.
duckhunt-entry-file-save
ChatGPTSaves a file from the source as an attachment of a task: downloads it and persists it in duckhunt (from then on it is read with duckhunt-attachment-read and appears in attachments of duckhunt-target-get). Use it when the file should stay with the task (a contract, a specification, the bug screenshot) instead of reading it once. 10 MB limit and subject to the quota of the task owner; requires write permission on it. Returns the created metadata.
duckhunt-entry-get
ChatGPTReturns an entry with its context: per-source extension, tasks it belongs to, custom fields (with their value), its work notes, the latest agent runs on it (agentRuns: r#N, status and verdict; the whole thread with duckhunt-agent-run-get) and earlier runs on other entries that look alike (similarRuns: same exception, table, alarm family, ticket key or title, with how they match and their verdict; data from other runs, it may not apply). id accepts the numeric local id or an external id: a jira key (OKT-123), an already ingested linear identifier (ENG-123), a linear url (linear.app/<org>/issue/ENG-123) or a figma url (figma.com/design/...); if it is not imported yet, it fetches it from the source and saves it silently (figma requires a figma connection of the user; returns file metadata: name, project, editor, thumbnail, last edit). For emails, body is the full compacted thread (all messages, not just the snippet) and emailThread exposes the structured per-message version, both served from the local cache; each message lists its attachments in attachments (filename, contentType, sizeBytes, index); the content is read with duckhunt-entry-file-read, whose ref for an email is <messageId>#<index> (or ask duckhunt-entry-file-list for them already built). Images pasted in the body also appear there (inline: true + contentId), and the body references them as : if you need to SEE a screenshot from the email, match that contentId with the attachment and read it by that ref.
duckhunt-entry-list
ChatGPTLists entries (polled items) of the workspace bound to the token. Filters: category (tickets/code/email/notes/monitoring) or provider (jira/bitbucket/gmail/...), mutually exclusive; provider wins if both are given. status, q, unclaimed. allWorkspaces=true aggregates ALL workspaces of the user (each item carries workspaceId).
duckhunt-entry-list-transitions
ChatGPTLists the transitions available for the entry. Each one includes fields: the fields the workflow asks for when applying it (resolution when closing, etc.) with their options and currentValue (what the issue already has; a required field with a currentValue can be omitted); the required ones are passed in duckhunt-entry-transition.fields.
duckhunt-entry-set-description
ChatGPTREPLACES the whole description of the entry in its source (jira, bitbucket/github pr). Markdown; each provider converts it to its own format. Refreshes the local cache after the write.
duckhunt-entry-set-field
ChatGPTWrites a field of the entry in its source (jira today): assignee (accountId), priority (id), sprint (numeric id), duedate (YYYY-MM-DD), estimate/remainingEstimate (jira duration "2w 3d 4h 30m") with string|null (null clears); labels (names), fixVersions/affectsVersions/components (ids) with an array of strings REPLACING the whole set. The ids come from duckhunt-entry-field-options. Refreshes the local cache after the write.
duckhunt-entry-set-title
ChatGPTRenames the entry by writing to its source (jira summary, bitbucket/github pr title, github issue). Refreshes the local cache after the write.
duckhunt-entry-suggestions
ChatGPTSuggests entries related to this one (same external_id, or ticket keys mentioned in its title or note content)
duckhunt-entry-transition
ChatGPTApplies a transition to the entry; transitionId comes from duckhunt-entry-list-transitions. If that transition declares required fields (e.g. resolution when closing), pass them in fields as {fieldId: value} with the ids of their options; if you omit them, they are filled with the default value of the source (or its first option) ONLY if the issue has them empty.
duckhunt-inbox
ChatGPTLists unread inbox events of the workspace bound to the token, with the task(s) associated with each entry. Filters: category or provider (mutually exclusive; provider wins). allWorkspaces=true aggregates all workspaces of the user.
duckhunt-inbox-seen
ChatGPTMarks an event as seen
duckhunt-inbox-snooze
ChatGPTHides an event until a future date (iso8601)
duckhunt-insights
ChatGPTThe INSIGHTS views of the user for a period, the same data their /insights tabs show. view: summary (done, created, tracked time by signal and day, agent cost, inbox volume and triage, open board now, each with the previous comparable span and a series), findings (deterministic flags of what deserves action: review_merged, review_queue, stale_wip, unattributed_code, noisy_source, agent_rule_cost; without the dismissed ones), time (per local day totals and, with blocks=true, its de-overlapped blocks hour by hour; time per task and per repo with what reached no task, meetings, tempo per day; a quarter has no blocks), flow (cycle time p50/p85 over 90 days, started work with its age, where finished work waited by status, reopened tasks), agents (runs and cost per day and origin, models, usefulness per automation rule, the most expensive conversations, questions and permission waits, machine occupancy) or sources (where inbox notices ended up per provider, triage, the mute rule that would help backtested on 30 days, the most repeated items). Everything follows scope: with workspace, time and meetings are only what belongs to its tasks, issues, repos and calendars; with all, the whole user. Optional period (day|week|month|quarter, default week), anchor (yyyy-mm-dd inside the period; default today for day and yesterday otherwise) and scope (workspace = the active one, all = every own workspace).
duckhunt-jira-create
ChatGPTCreates a new jira issue and ingests it as a local entry. Optional targetId attaches it to that task in the same step (useful for derived work: "this needs a follow-up ticket"). Valid projectKey/issueType via duckhunt-jira-projects. Returns {entryId, key}.
duckhunt-jira-projects
ChatGPTLists the jira projects where you can create issues, with their issue types. Use it to discover valid projectKey/issueType before duckhunt-jira-create. A project with empty issueTypes is one whose metadata could not be read: do not use it to create. Slow (1-3s); cache the result in your context.
duckhunt-label-list
ChatGPTLists the labels of the user with their color and the number of labeled targets (usageCount)
duckhunt-label-set
ChatGPTReplaces the label set of a task BY NAME. Names that do not exist are created inline (auto color from the palette). Empty list = remove all. Returns the resulting labels.
duckhunt-list-monitors
ChatGPTLists monitors of the workspace bound to the token (aws cloudwatch alarms + open nightwatch issues + uptime kuma monitors) with derived severity. All of them live in category=monitoring; filter by provider (aws|nightwatch|uptime_kuma) or severity. Resolved nightwatch issues are omitted. allWorkspaces=true aggregates the monitors of ALL the workspaces of the user.
duckhunt-mention-suggest
ChatGPTSuggests users to mention in the entry (jira: user search; bitbucket: workspace members). Returns canonical tokens ready for duckhunt-entry-comment.
duckhunt-note-add
ChatGPTAdds a work note to a task (targetId) or to an entry (entryId), exactly one of them. It is YOUR channel to leave state visible to the user and context for future agent sessions: kind=progress (progress of the ongoing work), blocker (what blocks you), result (summary/handoff when finishing), note (free context, default). body in markdown. summary: ONE sentence in plain text (max. 200 chars) with the verdict; it is the only thing the user reads in the mobile notification WITHOUT expanding it, so write it to be understood on its own. Depending on notification preferences, adding the note can send a push through the user's configured push service. data optional: free json object for structured state (branch, pr url, checklist...). Use data.context (conversationId, host, repoPath, memoryDir...) so that a future invocation resumes in its environment. author: identify yourself (e.g. "claude-code"). Notes appear embedded in duckhunt-target-get and duckhunt-entry-get. Inside an agent run your answer goes through duckhunt-run-reply, never here: a note holds the state of the task you are working on when your prompt asks you to track it, or what the user asks for. Related: duckhunt-note-update (keep the same note alive), duckhunt-note-list, duckhunt-note-delete.
duckhunt-note-delete
ChatGPTDeletes one of your own work notes
duckhunt-note-list
ChatGPTLists the work notes of a task (targetId) or entry (entryId), in chronological order. Usually not needed: duckhunt-target-get and duckhunt-entry-get already embed them. Useful to filter by kind (e.g. only blockers).
duckhunt-note-update
ChatGPTUpdates one of your own work notes (body, kind and/or data). Useful to keep a single progress note alive instead of piling up one per step. data is MERGED over the existing state (shallow): the keys you pass are updated and the rest are kept, so you can change a single key (e.g. status) without resending everything. A null value on a key deletes it; data:null (top-level) deletes all the structured state; omitting data leaves it untouched. The noteId comes from duckhunt-note-add or from the notes embedded in duckhunt-target-get / duckhunt-entry-get. Related: duckhunt-note-list, duckhunt-note-delete.
duckhunt-pipeline-logs
ChatGPTLog tail (~64KB) of a step of the pr pipeline. Without stepUuid it resolves the first failed step of the run; pipelineUuid is optional (default: the last persisted run). Use it after a ci_failed event to read the build error and fix it.
duckhunt-pipeline-status
ChatGPTCI status (bitbucket pipelines) of the pr: last run of the source branch persisted by the poller (state PENDING|IN_PROGRESS|COMPLETED, result SUCCESSFUL|FAILED|ERROR|STOPPED). fresh=true queries bitbucket live and adds the recent runs of the branch.
duckhunt-pr-merge
ChatGPTMerges a pr/mr into its destination in the source (bitbucket/github). strategy is the raw provider name (bitbucket: merge_commit|squash|fast_forward); if omitted, the repo default is used. closeSourceBranch closes the source branch after merging. Before merging, review the doneChecklist of the target (open review tasks). Refreshes the local cache after the merge.
duckhunt-pr-open
ChatGPTOpens the pull request of a repo linked to the target (see duckhunt-target-branch-set) against bitbucket/github and ingests it as an entry attached to the target in the same step. repoId can be omitted only if the target has ONE linked repo. title defaults to the target title; description is only sent if passed explicitly. Returns {entryId, url, prNumber}.
duckhunt-pr-update-branch
ChatGPTUpdates the pr branch with its destination (merges base into head, in the source). github supports it; bitbucket cloud has no public sync api. Useful when the pr fell behind its base before merging. Refreshes the local cache afterwards.
duckhunt-search
ChatGPTSearch the tasks and entries of the workspace bound to the token, with the same engine as the app's cmd+k: title, external id and source, status, labels, descriptions and indexed content (email sender and snippet, pull request repo and branch, exception, alarm). Every word must match somewhere, in any order, ignoring case and accents. Use it to get your bearings ("what is there about OKT-1234?") and before creating a task, to avoid duplicates. Each hit has its ref (t#12, e#345), status, where it matched, a snippet when the match is in the content, and for entries the tasks they are attached to; read the full row with duckhunt-target-get or duckhunt-entry-get. The response says how many matched in total and whether the list was truncated; archived tasks come last and are flagged.
duckhunt-set-custom-field
ChatGPTSets (or clears with an empty/null value) the value of a custom field on a target or an entry. Pass EXACTLY one of targetId/entryId. fieldId is the definition id (visible in customFields of duckhunt-target-get/entry-get). value is text: number→numeric, date→yyyy-mm-dd, checkbox→0/1, select→one option, multi_select→json array of options. Returns the resolved fields.
duckhunt-share-grant
ChatGPTShares a target of YOURS (targetId, contract 36) or a whole workspace of YOURS (workspaceId, contract 43) with another duckhunt user by email. Exactly one of targetId/workspaceId. role=viewer (read-only) or editor (moves targets, leaves work notes; in a workspace it also creates targets). Idempotent: re-granting updates the role and can downgrade an existing editor to viewer. The recipient must have an account. Returns the grant {granteeUserId, email, role}.
duckhunt-share-list
ChatGPTLists who a target of YOURS (targetId) or a workspace of YOURS (workspaceId) is shared with: active grants (email + role). Exactly one of the two. Owner only.
duckhunt-share-revoke
ChatGPTRevokes the access of a user to a target of YOURS (targetId) or to a workspace of YOURS (workspaceId). Exactly one of the two. Owner only. Idempotent.
duckhunt-shared-list
ChatGPTLists what OTHER users have shared with you: items = individual targets (contract 36: validation / handoff; id, title, status, owner email and your role) and workspaces = whole workspaces (contract 43: id, name, owner and role). viewer=read-only, editor=you can write. Open a target with duckhunt-target-get (you will see the collaborative layer + your own per-source entries); a shared workspace is worked on with an mcp token bound to it (activate it in the ui and re-authorize) or by passing it as workspaceId when creating.
duckhunt-status-list
ChatGPTLists the kanban statuses of the user (built-in + custom) with their key, label and color. Use the key (e.g. "in_progress" or "c1") as the status value in target-create / target-update. locked lists the columns locked in the active workspace: no task can be created in, moved into or out of, reordered, archived or deleted from them until the user unlocks them on the board.
duckhunt-target-add-time
ChatGPTAdjusts the agent session time of a target WITH SIGN (the session signal of duckhunt-target-time). Corrects undercounted time: implicit tracking splits your session when you go >60min without touching duckhunt (long stretches of editing/compiling/running without tool calls), so your real time may exceed the recorded one. POSITIVE minutes adds the missing ones; NEGATIVE corrects downwards if you overshot. To set an absolute total use duckhunt-target-set-time. NOT idempotent: each call adjusts again, do not retry blindly. Requires mcp time tracking enabled in settings. Returns the updated total.
duckhunt-target-attach
ChatGPTAttaches an entry to a task
duckhunt-target-branch-delete
ChatGPTUnlinks a repo from the target (row of repos from duckhunt-target-get). It does not touch the already opened pr or its entry.
duckhunt-target-branch-set
ChatGPTLinks a repo and its branches to a target so its pull request can be opened with duckhunt-pr-open. Adding NEVER overwrites previous rows: a target can accumulate several prs, even from the same repo (another source branch, or the same one against dev and master); only repeating the exact coordinates is idempotent (returns the existing row). repo = workspace/slug (bitbucket) or owner/repo (github); omitted destBranch = main branch of the repo when opening. Configured repos come in repos of duckhunt-target-get (stale branches are removed with duckhunt-target-branch-delete). Do it when creating the working branch: it leaves the coordinates ready to open the pr when done.
duckhunt-target-create
ChatGPTCreates a task, optionally with initial attached entries. Optional parentId to be born as a subtask of another target. isEpic=true creates an epic (organizational container: groups subtasks, with no work or status of its own). Optional priority (1=urgent..4=low). Optional taskType classifies the task (catalog key, built-in feature|bug|chore|improvement|research or custom; list them with duckhunt-task-type-list). Optional status to start directly in a column (e.g. in_progress when claiming and starting). Optional note leaves an initial work note kind=progress (attributed to author); it collapses the claim+start flow into a single call. Optional workspaceId creates it in another workspace of the user (default: the active one). Returns {id, workspaceId, url, created}; created=false if a recent target with the same title already existed (idempotent on retries).
duckhunt-target-detach
ChatGPTRemoves an entry from a task
duckhunt-target-follow-up
ChatGPTCreates a new version ("v2"/follow-up) of a target: a CLEAN task linked to the original (copies the title with suffix (vN), description and labels; its own board and timeline), without touching or cluttering the original. Use it when a closed task has to be reopened or redone instead of reviving its history. Different from a subtask/epic: it is not hierarchy. Returns the id of the new version. The version chain appears in versions of duckhunt-target-get.
duckhunt-target-get
ChatGPTReturns a task with all its attached entries, subtasks, labels, custom fields (with their value), its work notes (state/memory left by agents and the user; read them before resuming work), the latest agent runs launched from it or on its entries (agentRuns: r#N, status and verdict; the whole thread with duckhunt-agent-run-get), earlier runs on other items that look alike (similarRuns: same exception, table, alarm family, ticket key or title, with how they match and their verdict; data from other runs, it may not apply) and its associated repos, each with the already ingested commits of its branch (repos[].commits, most recent first: the code that was written even if nobody noted it).
duckhunt-target-link
ChatGPTRelates two tasks ("related tasks"), separate from the hierarchy (subtasks/epics) and versions. kind: "relates" (symmetric), "blocks" (directional: targetId BLOCKS relatedTargetId; the other one will see it as "blocked by"), "duplicates" (symmetric). Accepts tasks from different workspaces. Idempotent. Relations appear in links of duckhunt-target-get.
duckhunt-target-list
ChatGPTLists the tasks (targets) in the workspace of the token with entry counts per source and their labels. Optional status: a catalog key (built-in backlog|todo|in_progress|in_review|done|canceled or custom; list them with duckhunt-status-list). Optional parent: "root" = roots only, number = only direct children of that id. Optional labels: label names of the user, filters with OR semantics. allWorkspaces=true aggregates tasks from ALL workspaces of the user.
duckhunt-target-merge
ChatGPTMerges (reconciles) the task sourceId INTO destId and DELETES the source: entries, notes, labels, attachments, custom fields, time, subtasks and shares move to the destination (the scalar fields of the destination win; gaps are filled with those of the source). Entries that the destination owner has no copy of in their workspace are detached (not deleted). Supports shared tasks: you need write permission (owner or editor) on BOTH; when absorbing a task from another owner, that owner receives an editor grant on the destination.
duckhunt-target-move
ChatGPTMoves a task (and its whole subtree of subtasks) to another workspace of the user. Reconciles what is per-workspace: a status/type that does not exist in the destination is adjusted (status→todo), the kanban order is recalculated and the custom fields of the source are discarded. Entries that do not live in the destination are DETACHED from the task (not deleted). Owner only; get the destination workspaceId from duckhunt-workspace-list (id + name of each workspace).
duckhunt-target-set-time
ChatGPTSets the agent session time of a target to an ABSOLUTE total in minutes (the session signal of duckhunt-target-time), correcting the difference with what has been recorded so far. Use it when you know the real total time and want the signal to reflect it exactly, instead of adding/subtracting blindly with add-time. minutes >= 0. It is idempotent with respect to the total (setting it twice to the same value leaves the same total). Requires mcp time tracking enabled in settings. Returns the updated total.
duckhunt-target-stats
ChatGPTReturns task counts by status + orphan entries for the dashboard
duckhunt-target-suggestions
ChatGPTSuggests unattached entries related to the ones already attached to the task
duckhunt-target-time
ChatGPTTracked time of a task. timeline is the authoritative total: the wall-clock union of every signal (manual clock, coding time from wakatime, mcp agent sessions, work in the duckhunt ui) with overlaps counted once. bySignal sums to totalSeconds (an overlapping minute goes to the most reliable signal: manual > code > agent > app), byDay is per local day and codeVia says how coding time reached this task: assigned (the user assigned those coding blocks to the task by hand), branch (jira key in the branch), repo (a work branch linked only to this task, never a trunk such as main or a branch other tasks merge into), anchor (coding in a compatible repo while a session of this task was running) or commit (jira keys in the day's own commit messages); codeByBranch = its coding time by (project, branch, issue). The other fields are raw per-signal detail and must NOT be added up: session = agent sessions, app = ui work, worklog = tracked-vs-logged state in tempo per key, provenance = which signal the ALREADY logged time came from.
duckhunt-target-unlink
ChatGPTRemoves a relation between two tasks (the one matching the pair and kind, in either direction). kind: relates | blocks | duplicates. Idempotent.
duckhunt-target-update
ChatGPTUpdates fields of a task (status, title, description, etc.). status accepts any key from the catalog (built-in or custom; list them with duckhunt-status-list). descriptionEntryId links an attached entry (any source) as a live description; mainEntryId marks an attached entry as the main one of the target. null in either of them unlinks. parentId re-parents the target (null = make it a root); rejects cycles.
duckhunt-task-type-list
ChatGPTLists the task types of the user (built-in feature|bug|chore|improvement|research + custom) with their key, label, color and icon, plus the keys hidden in the active workspace. Use the key (e.g. "bug" or "tt1") as the taskType value in target-create / target-update.
duckhunt-tempo-list-worklogs
ChatGPTLOCAL read-back of the worklog ledger that duckhunt pushed to tempo (does NOT call tempo: lists what duckhunt logged, with the source signal). Each row: source (code/agent/manual/app/explicit), jiraKey, day, seconds, tempoWorklogId (null = tracked but not pushed yet). For reconciling what was synced and why. Does NOT see worklogs created outside duckhunt. Optional from/to/jiraKey filters.
duckhunt-tempo-log-worklog
ChatGPTCreates one new worklog in Tempo Cloud for the Jira issue of an owned entry, using the connected Tempo account. This writes time to an external service; call only when the user requests time logging. seconds is a whole number of at least 60. date and startTime use the user timezone. If startTime is omitted, use the live agent session start, or a block ending now when there is no live session. If date is omitted, use the date of that resolved block start. Each successful call creates a new worklog; do not retry an uncertain result without checking duckhunt-tempo-list-worklogs. Requires connected Tempo and Jira accounts. Does not update or delete existing worklogs.
duckhunt-tempo-manage-day
ChatGPTMarks (managed=true, default) or releases (false) a (jira issue, day) as MANUALLY MANAGED: tempo auto-sync stops adding time on top of it; the manual correction wins. Use it after balancing a day by hand in tempo so duckhunt does not stack slivers on it on the next tick. The auto-sync also sets these locks by itself when it reads tempo back and finds a worklog on that issue and day created, edited or deleted outside duckhunt. Explicit logging (duckhunt-tempo-log-worklog) is NOT affected: it is a deliberate action. Returns the final state and the full list of locks of the user.
duckhunt-unattributed-time
ChatGPTUNATTRIBUTED coding time: the part of your coding wall-clock (wakatime, overlaps counted once) that reached no task and no jira issue by any route (branch key, task branch, a session of a task in the same repo, or keys in that day's own commit messages). Makes the zero honest: a low code time on a task does not mean no work was done, check this. codeSeconds = all coding time in the range, unattributedSeconds = the remainder, attributedByVia = how the rest was attributed, plus the remainder by day and by (project, branch). Optional from/to (yyyy-mm-dd, inclusive).
duckhunt-user-note-create
ChatGPTCreates a note of the user (standalone markdown document, visible and editable in /notes). To report progress on a task use duckhunt-note-add (work notes), not this.
duckhunt-user-note-delete
ChatGPTDeletes a note of the user (standalone document). Its agent conversations are kept in /agents.
duckhunt-user-note-get
ChatGPTReads a note of the user (standalone markdown document) with its full content.
duckhunt-user-note-list
ChatGPTLists the notes of the user (standalone markdown documents in duckhunt, NOT the work notes of targets/entries). Ordered by last edit. q filters by title.
duckhunt-user-note-update
ChatGPTUpdates the title and/or content of a note of the user.
duckhunt-workspace-list
ChatGPTLists the workspaces of the user with their id, name, whether it is the default and which one is active for the token. Translates a workspace name ("personal", "okticket") into the workspaceId required by duckhunt-target-create and duckhunt-target-move. The rest of the tools operate only on the active workspace unless they accept allWorkspaces=true.