feat(ui): add tag indicator to all CLI commands
- shows 🏷️ tag: tagname for complete context visibility across 15+ commands
This commit is contained in:
5
.changeset/yellow-olives-admire.md
Normal file
5
.changeset/yellow-olives-admire.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"task-master-ai": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Adds tag to CLI output so you know which tag you are performing operations on. Already supported in the MCP response.
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"currentTag": "master",
|
"currentTag": "test-prd-tag",
|
||||||
"lastSwitched": "2025-06-13T07:32:07.706Z",
|
"lastSwitched": "2025-06-13T07:48:41.146Z",
|
||||||
"branchTagMapping": {},
|
"branchTagMapping": {},
|
||||||
"migrationNoticeShown": true
|
"migrationNoticeShown": true
|
||||||
}
|
}
|
||||||
@@ -699,7 +699,6 @@ function registerCommands(programInstance) {
|
|||||||
const force = options.force || false;
|
const force = options.force || false;
|
||||||
const append = options.append || false;
|
const append = options.append || false;
|
||||||
const research = options.research || false;
|
const research = options.research || false;
|
||||||
const tag = options.tag;
|
|
||||||
let useForce = force;
|
let useForce = force;
|
||||||
const useAppend = append;
|
const useAppend = append;
|
||||||
|
|
||||||
@@ -709,6 +708,12 @@ function registerCommands(programInstance) {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve tag using standard pattern
|
||||||
|
const tag = options.tag || getCurrentTag(projectRoot) || 'master';
|
||||||
|
|
||||||
|
// Show current tag context
|
||||||
|
displayCurrentTagIndicator(tag);
|
||||||
|
|
||||||
// Helper function to check if there are existing tasks in the target tag and confirm overwrite
|
// Helper function to check if there are existing tasks in the target tag and confirm overwrite
|
||||||
async function confirmOverwriteIfNeeded() {
|
async function confirmOverwriteIfNeeded() {
|
||||||
// Check if there are existing tasks in the target tag
|
// Check if there are existing tasks in the target tag
|
||||||
@@ -855,7 +860,6 @@ function registerCommands(programInstance) {
|
|||||||
const fromId = parseInt(options.from, 10); // Validation happens here
|
const fromId = parseInt(options.from, 10); // Validation happens here
|
||||||
const prompt = options.prompt;
|
const prompt = options.prompt;
|
||||||
const useResearch = options.research || false;
|
const useResearch = options.research || false;
|
||||||
const tag = options.tag;
|
|
||||||
|
|
||||||
const projectRoot = findProjectRoot();
|
const projectRoot = findProjectRoot();
|
||||||
if (!projectRoot) {
|
if (!projectRoot) {
|
||||||
@@ -863,6 +867,12 @@ function registerCommands(programInstance) {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve tag using standard pattern
|
||||||
|
const tag = options.tag || getCurrentTag(projectRoot) || 'master';
|
||||||
|
|
||||||
|
// Show current tag context
|
||||||
|
displayCurrentTagIndicator(tag);
|
||||||
|
|
||||||
// Check if there's an 'id' option which is a common mistake (instead of 'from')
|
// Check if there's an 'id' option which is a common mistake (instead of 'from')
|
||||||
if (
|
if (
|
||||||
process.argv.includes('--id') ||
|
process.argv.includes('--id') ||
|
||||||
@@ -942,7 +952,6 @@ function registerCommands(programInstance) {
|
|||||||
.action(async (options) => {
|
.action(async (options) => {
|
||||||
try {
|
try {
|
||||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||||
const tag = options.tag;
|
|
||||||
|
|
||||||
const projectRoot = findProjectRoot();
|
const projectRoot = findProjectRoot();
|
||||||
if (!projectRoot) {
|
if (!projectRoot) {
|
||||||
@@ -950,6 +959,12 @@ function registerCommands(programInstance) {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve tag using standard pattern
|
||||||
|
const tag = options.tag || getCurrentTag(projectRoot) || 'master';
|
||||||
|
|
||||||
|
// Show current tag context
|
||||||
|
displayCurrentTagIndicator(tag);
|
||||||
|
|
||||||
// Validate required parameters
|
// Validate required parameters
|
||||||
if (!options.id) {
|
if (!options.id) {
|
||||||
console.error(chalk.red('Error: --id parameter is required'));
|
console.error(chalk.red('Error: --id parameter is required'));
|
||||||
@@ -1108,7 +1123,6 @@ function registerCommands(programInstance) {
|
|||||||
.action(async (options) => {
|
.action(async (options) => {
|
||||||
try {
|
try {
|
||||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||||
const tag = options.tag;
|
|
||||||
|
|
||||||
const projectRoot = findProjectRoot();
|
const projectRoot = findProjectRoot();
|
||||||
if (!projectRoot) {
|
if (!projectRoot) {
|
||||||
@@ -1116,6 +1130,12 @@ function registerCommands(programInstance) {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve tag using standard pattern
|
||||||
|
const tag = options.tag || getCurrentTag(projectRoot) || 'master';
|
||||||
|
|
||||||
|
// Show current tag context
|
||||||
|
displayCurrentTagIndicator(tag);
|
||||||
|
|
||||||
// Validate required parameters
|
// Validate required parameters
|
||||||
if (!options.id) {
|
if (!options.id) {
|
||||||
console.error(chalk.red('Error: --id parameter is required'));
|
console.error(chalk.red('Error: --id parameter is required'));
|
||||||
@@ -2133,7 +2153,6 @@ ${result.result}
|
|||||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||||
const taskId = options.id;
|
const taskId = options.id;
|
||||||
const dependencyId = options.dependsOn;
|
const dependencyId = options.dependsOn;
|
||||||
const tag = options.tag;
|
|
||||||
|
|
||||||
const projectRoot = findProjectRoot();
|
const projectRoot = findProjectRoot();
|
||||||
if (!projectRoot) {
|
if (!projectRoot) {
|
||||||
@@ -2141,6 +2160,12 @@ ${result.result}
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve tag using standard pattern
|
||||||
|
const tag = options.tag || getCurrentTag(projectRoot) || 'master';
|
||||||
|
|
||||||
|
// Show current tag context
|
||||||
|
displayCurrentTagIndicator(tag);
|
||||||
|
|
||||||
if (!taskId || !dependencyId) {
|
if (!taskId || !dependencyId) {
|
||||||
console.error(
|
console.error(
|
||||||
chalk.red('Error: Both --id and --depends-on are required')
|
chalk.red('Error: Both --id and --depends-on are required')
|
||||||
@@ -2179,7 +2204,6 @@ ${result.result}
|
|||||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||||
const taskId = options.id;
|
const taskId = options.id;
|
||||||
const dependencyId = options.dependsOn;
|
const dependencyId = options.dependsOn;
|
||||||
const tag = options.tag;
|
|
||||||
|
|
||||||
const projectRoot = findProjectRoot();
|
const projectRoot = findProjectRoot();
|
||||||
if (!projectRoot) {
|
if (!projectRoot) {
|
||||||
@@ -2187,6 +2211,12 @@ ${result.result}
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve tag using standard pattern
|
||||||
|
const tag = options.tag || getCurrentTag(projectRoot) || 'master';
|
||||||
|
|
||||||
|
// Show current tag context
|
||||||
|
displayCurrentTagIndicator(tag);
|
||||||
|
|
||||||
if (!taskId || !dependencyId) {
|
if (!taskId || !dependencyId) {
|
||||||
console.error(
|
console.error(
|
||||||
chalk.red('Error: Both --id and --depends-on are required')
|
chalk.red('Error: Both --id and --depends-on are required')
|
||||||
@@ -2227,13 +2257,18 @@ ${result.result}
|
|||||||
)
|
)
|
||||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||||
.action(async (options) => {
|
.action(async (options) => {
|
||||||
const tag = options.tag;
|
|
||||||
const projectRoot = findProjectRoot();
|
const projectRoot = findProjectRoot();
|
||||||
if (!projectRoot) {
|
if (!projectRoot) {
|
||||||
console.error(chalk.red('Error: Could not find project root.'));
|
console.error(chalk.red('Error: Could not find project root.'));
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve tag using standard pattern
|
||||||
|
const tag = options.tag || getCurrentTag(projectRoot) || 'master';
|
||||||
|
|
||||||
|
// Show current tag context
|
||||||
|
displayCurrentTagIndicator(tag);
|
||||||
|
|
||||||
await validateDependenciesCommand(options.file || TASKMASTER_TASKS_FILE, {
|
await validateDependenciesCommand(options.file || TASKMASTER_TASKS_FILE, {
|
||||||
context: { projectRoot, tag }
|
context: { projectRoot, tag }
|
||||||
});
|
});
|
||||||
@@ -2250,13 +2285,18 @@ ${result.result}
|
|||||||
)
|
)
|
||||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||||
.action(async (options) => {
|
.action(async (options) => {
|
||||||
const tag = options.tag;
|
|
||||||
const projectRoot = findProjectRoot();
|
const projectRoot = findProjectRoot();
|
||||||
if (!projectRoot) {
|
if (!projectRoot) {
|
||||||
console.error(chalk.red('Error: Could not find project root.'));
|
console.error(chalk.red('Error: Could not find project root.'));
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve tag using standard pattern
|
||||||
|
const tag = options.tag || getCurrentTag(projectRoot) || 'master';
|
||||||
|
|
||||||
|
// Show current tag context
|
||||||
|
displayCurrentTagIndicator(tag);
|
||||||
|
|
||||||
await fixDependenciesCommand(options.file || TASKMASTER_TASKS_FILE, {
|
await fixDependenciesCommand(options.file || TASKMASTER_TASKS_FILE, {
|
||||||
context: { projectRoot, tag }
|
context: { projectRoot, tag }
|
||||||
});
|
});
|
||||||
@@ -2273,8 +2313,6 @@ ${result.result}
|
|||||||
)
|
)
|
||||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||||
.action(async (options) => {
|
.action(async (options) => {
|
||||||
const tag = options.tag;
|
|
||||||
|
|
||||||
const projectRoot = findProjectRoot();
|
const projectRoot = findProjectRoot();
|
||||||
if (!projectRoot) {
|
if (!projectRoot) {
|
||||||
console.error(chalk.red('Error: Could not find project root.'));
|
console.error(chalk.red('Error: Could not find project root.'));
|
||||||
@@ -2282,7 +2320,10 @@ ${result.result}
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use the provided tag, or the current active tag, or default to 'master'
|
// Use the provided tag, or the current active tag, or default to 'master'
|
||||||
const targetTag = tag || getCurrentTag(projectRoot) || 'master';
|
const targetTag = options.tag || getCurrentTag(projectRoot) || 'master';
|
||||||
|
|
||||||
|
// Show current tag context
|
||||||
|
displayCurrentTagIndicator(targetTag);
|
||||||
|
|
||||||
// Tag-aware report file naming: master -> task-complexity-report.json, other tags -> task-complexity-report_tagname.json
|
// Tag-aware report file naming: master -> task-complexity-report.json, other tags -> task-complexity-report_tagname.json
|
||||||
const reportPath =
|
const reportPath =
|
||||||
@@ -2328,7 +2369,12 @@ ${result.result}
|
|||||||
const parentId = options.parent;
|
const parentId = options.parent;
|
||||||
const existingTaskId = options.taskId;
|
const existingTaskId = options.taskId;
|
||||||
const generateFiles = !options.skipGenerate;
|
const generateFiles = !options.skipGenerate;
|
||||||
const tag = options.tag;
|
|
||||||
|
// Resolve tag using standard pattern
|
||||||
|
const tag = options.tag || getCurrentTag(projectRoot) || 'master';
|
||||||
|
|
||||||
|
// Show current tag context
|
||||||
|
displayCurrentTagIndicator(tag);
|
||||||
|
|
||||||
if (!parentId) {
|
if (!parentId) {
|
||||||
console.error(
|
console.error(
|
||||||
@@ -2769,7 +2815,6 @@ ${result.result}
|
|||||||
.action(async (options) => {
|
.action(async (options) => {
|
||||||
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
const tasksPath = options.file || TASKMASTER_TASKS_FILE;
|
||||||
const taskIdsString = options.id;
|
const taskIdsString = options.id;
|
||||||
const tag = options.tag;
|
|
||||||
|
|
||||||
const projectRoot = findProjectRoot();
|
const projectRoot = findProjectRoot();
|
||||||
if (!projectRoot) {
|
if (!projectRoot) {
|
||||||
@@ -2777,6 +2822,12 @@ ${result.result}
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve tag using standard pattern
|
||||||
|
const tag = options.tag || getCurrentTag(projectRoot) || 'master';
|
||||||
|
|
||||||
|
// Show current tag context
|
||||||
|
displayCurrentTagIndicator(tag);
|
||||||
|
|
||||||
if (!taskIdsString) {
|
if (!taskIdsString) {
|
||||||
console.error(chalk.red('Error: Task ID(s) are required'));
|
console.error(chalk.red('Error: Task ID(s) are required'));
|
||||||
console.error(
|
console.error(
|
||||||
|
|||||||
@@ -62,15 +62,15 @@ function displayTaggedTasksFYI(data) {
|
|||||||
* Display a small, non-intrusive indicator showing the current tag context
|
* Display a small, non-intrusive indicator showing the current tag context
|
||||||
* @param {string} tagName - The tag name to display
|
* @param {string} tagName - The tag name to display
|
||||||
* @param {Object} options - Display options
|
* @param {Object} options - Display options
|
||||||
* @param {boolean} [options.skipIfMaster=true] - Don't show indicator if tag is 'master'
|
* @param {boolean} [options.skipIfMaster=false] - Don't show indicator if tag is 'master'
|
||||||
* @param {boolean} [options.dim=false] - Use dimmed styling
|
* @param {boolean} [options.dim=false] - Use dimmed styling
|
||||||
*/
|
*/
|
||||||
function displayCurrentTagIndicator(tag, options = {}) {
|
function displayCurrentTagIndicator(tag, options = {}) {
|
||||||
if (isSilentMode()) return;
|
if (isSilentMode()) return;
|
||||||
|
|
||||||
const { skipIfMaster = true, dim = false } = options;
|
const { skipIfMaster = false, dim = false } = options;
|
||||||
|
|
||||||
// Skip display for master tag by default (since it's the default context)
|
// Skip display for master tag only if explicitly requested
|
||||||
if (skipIfMaster && tag === 'master') return;
|
if (skipIfMaster && tag === 'master') return;
|
||||||
|
|
||||||
// Create a small, tasteful tag indicator
|
// Create a small, tasteful tag indicator
|
||||||
|
|||||||
Reference in New Issue
Block a user