tissue update / tissue close / tissue reopen
Update issue metadata and status.
Tissue Commands
# Update status
tissue update 42 --status "in-progress"
tissue close 42
tissue reopen 42
# Update priority and tags
tissue update 42 --priority critical
tissue tag 42 "needs-review" "v2.0"
tissue untag 42 "wontfix"
# Add comment
tissue comment 42 "Started working on this"
Manual Workflow (bash + git)
Update issue status
# Change status field using yq
update_status() {
ISSUE_NUM="$1"
NEW_STATUS="$2"
cd ../issues
PADDED_NUM=$(printf "%03d" "$ISSUE_NUM")
FILE=$(ls ${PADDED_NUM}_*.md 2>/dev/null | head -1)
if [ -z "$FILE" ]; then
echo "Issue #${ISSUE_NUM} not found"
return 1
fi
# Validate status
VALID=$(echo "$NEW_STATUS" | yq '. as $s | ["open", "in-progress", "closed", "blocked"] | contains([$s])')
if [ "$VALID" != "true" ]; then
echo "Invalid status: $NEW_STATUS"
return 1
fi
# Update status and timestamp using yq
yq --front-matter '
.status = "'"$NEW_STATUS"'" |
.updated = now
' -i "$FILE"
# Commit the change
git add "$FILE"
git commit -m "Update issue #${ISSUE_NUM}: status -> ${NEW_STATUS}"
echo "Issue #${ISSUE_NUM} status updated to: ${NEW_STATUS}"
}
update_status 42 "in-progress"
Close and reopen shortcuts
# Close issue
close_issue() {
ISSUE_NUM="$1"
update_status "$ISSUE_NUM" "closed"
# Optionally add closing comment
if [ -n "$2" ]; then
add_comment "$ISSUE_NUM" "Closed: $2"
fi
}
# Reopen issue
reopen_issue() {
ISSUE_NUM="$1"
update_status "$ISSUE_NUM" "open"
# Add reopening comment
add_comment "$ISSUE_NUM" "Reopened"
}
close_issue 42 "Fixed in commit abc123"
reopen_issue 42
Update priority
# Change priority field using yq
update_priority() {
ISSUE_NUM="$1"
NEW_PRIORITY="$2"
cd ../issues
PADDED_NUM=$(printf "%03d" "$ISSUE_NUM")
FILE=$(ls ${PADDED_NUM}_*.md 2>/dev/null | head -1)
if [ -z "$FILE" ]; then
echo "Issue #${ISSUE_NUM} not found"
return 1
fi
# Validate priority using yq
VALID=$(echo "$NEW_PRIORITY" | yq '. as $p | ["low", "medium", "high", "critical"] | contains([$p])')
if [ "$VALID" != "true" ]; then
echo "Invalid priority. Use: low, medium, high, or critical"
return 1
fi
# Update priority and timestamp
yq --front-matter '
.priority = "'"$NEW_PRIORITY"'" |
.updated = now
' -i "$FILE"
git add "$FILE"
git commit -m "Update issue #${ISSUE_NUM}: priority -> ${NEW_PRIORITY}"
}
update_priority 42 "critical"
Add and remove tags
# Add tags to issue using yq
add_tags() {
ISSUE_NUM="$1"
shift # Remove first argument
NEW_TAGS="$@"
cd ../issues
PADDED_NUM=$(printf "%03d" "$ISSUE_NUM")
FILE=$(ls ${PADDED_NUM}_*.md 2>/dev/null | head -1)
if [ -z "$FILE" ]; then
echo "Issue #${ISSUE_NUM} not found"
return 1
fi
# Add each new tag using yq
for tag in $NEW_TAGS; do
yq --front-matter '.tags += ["'"$tag"'"]' -i "$FILE"
done
# Remove duplicates and update timestamp
yq --front-matter '
.tags |= unique |
.updated = now
' -i "$FILE"
git add "$FILE"
git commit -m "Add tags to issue #${ISSUE_NUM}: ${NEW_TAGS}"
}
# Remove tags from issue using yq
remove_tags() {
ISSUE_NUM="$1"
shift
REMOVE_TAGS="$@"
cd ../issues
PADDED_NUM=$(printf "%03d" "$ISSUE_NUM")
FILE=$(ls ${PADDED_NUM}_*.md 2>/dev/null | head -1)
if [ -z "$FILE" ]; then
echo "Issue #${ISSUE_NUM} not found"
return 1
fi
# Remove each tag using yq
for tag in $REMOVE_TAGS; do
yq --front-matter '.tags -= ["'"$tag"'"]' -i "$FILE"
done
# Update timestamp
yq --front-matter '.updated = now' -i "$FILE"
git add "$FILE"
git commit -m "Remove tags from issue #${ISSUE_NUM}: ${REMOVE_TAGS}"
}
add_tags 42 "needs-review" "v2.0"
remove_tags 42 "wontfix"
Add comments to issue
# Add timestamped comment to issue body
add_comment() {
ISSUE_NUM="$1"
COMMENT="$2"
cd ../issues
PADDED_NUM=$(printf "%03d" "$ISSUE_NUM")
FILE=$(ls ${PADDED_NUM}_*.md 2>/dev/null | head -1)
if [ -z "$FILE" ]; then
echo "Issue #${ISSUE_NUM} not found"
return 1
fi
# Create comment with timestamp
TIMESTAMP=$(date -u +"%Y-%m-%d %H:%M:%S UTC")
AUTHOR=$(git config user.name)
COMMENT_BLOCK="
### Log
**[${TIMESTAMP}] ${AUTHOR}:**
${COMMENT}"
# Append comment to file
if ! grep -q "^### Log" "$FILE"; then
# Add Log section if it doesn't exist
echo "$COMMENT_BLOCK" >> "$FILE"
else
# Add comment in Log section
echo "
**[${TIMESTAMP}] ${AUTHOR}:**
${COMMENT}" >> "$FILE"
fi
# Update the timestamp using yq
yq --front-matter '.updated = now' -i "$FILE"
git add "$FILE"
git commit -m "Add comment to issue #${ISSUE_NUM}"
echo "Comment added to issue #${ISSUE_NUM}"
}
add_comment 42 "Started working on this issue. Found the root cause in module X."
Update assignee
# Assign issue to user using yq
assign_issue() {
ISSUE_NUM="$1"
ASSIGNEE="$2"
cd ../issues
PADDED_NUM=$(printf "%03d" "$ISSUE_NUM")
FILE=$(ls ${PADDED_NUM}_*.md 2>/dev/null | head -1)
if [ -z "$FILE" ]; then
echo "Issue #${ISSUE_NUM} not found"
return 1
fi
# Update assignee field using yq
if [ -n "$ASSIGNEE" ]; then
yq --front-matter '
.assignee = "'"$ASSIGNEE"'" |
.updated = now
' -i "$FILE"
COMMIT_MSG="Assign issue #${ISSUE_NUM} to ${ASSIGNEE}"
else
yq --front-matter '
.assignee = null |
.updated = now
' -i "$FILE"
COMMIT_MSG="Unassign issue #${ISSUE_NUM}"
fi
git add "$FILE"
git commit -m "$COMMIT_MSG"
}
# Unassign issue
unassign_issue() {
ISSUE_NUM="$1"
assign_issue "$ISSUE_NUM" ""
}
assign_issue 42 "@alice"
unassign_issue 42
What tissue does for you:
- Validates field values before updating
- Automatically updates timestamps
- Maintains audit trail through git history
- Supports bulk operations efficiently
- Handles comment threading and formatting
- Provides shortcuts for common operations
- Ensures data integrity during updates
- Manages assignee references consistently
- Supports undo through git mechanisms
- Integrates with hooks for notifications