Skip to content

Commit e188e72

Browse files
committed
feat: add global flags --context-dir, --quiet, --no-color
- --context-dir: Override context directory path (default: .context) - --quiet: Suppress non-essential output (config.Quiet variable) - --no-color: Disable colored output (sets color.NoColor = true) Updated all usages of config.DirContext to config.ContextDir() to support the --context-dir override. Signed-off-by: Jose Alekhinne <alekhinejose@gmail.com>
1 parent 3227f3f commit e188e72

17 files changed

Lines changed: 92 additions & 29 deletions

File tree

.context/TASKS.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@
1313

1414
- [x] T1.2.0.1b Add index markers to DECISIONS.md and LEARNINGS.md templates
1515
so new projects start with index structure #priority:low #added:2026-01-29
16-
- [ ] T1.2.5 feat: implement `--context-dir` global flag to override context directory path
16+
- [x] T1.2.5 feat: implement `--context-dir` global flag to override context directory path
1717
Documented in cli-reference.md as planned. Should allow `ctx --context-dir /path status`.
1818
#priority:low #added:2026-01-28
19-
- [ ] T1.2.6 feat: implement `--quiet` global flag to suppress non-essential output
19+
- [x] T1.2.6 feat: implement `--quiet` global flag to suppress non-essential output
2020
Documented in cli-reference.md as planned.
2121
#priority:low #added:2026-01-28
22-
- [ ] T1.2.7 feat: implement `--no-color` global flag to disable colored output
22+
- [x] T1.2.7 feat: implement `--no-color` global flag to disable colored output
2323
Documented in cli-reference.md as planned. Currently `NO_COLOR=1` env var works.
2424
#priority:low #added:2026-01-28
2525
- [ ] T1.2.9: upstream CI is broken (again)

internal/bootstrap/bootstrap.go

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package bootstrap
1717

1818
import (
19+
"github.com/fatih/color"
1920
"github.com/spf13/cobra"
2021

2122
"github.com/ActiveMemory/ctx/internal/cli/add"
@@ -35,6 +36,7 @@ import (
3536
"github.com/ActiveMemory/ctx/internal/cli/sync"
3637
"github.com/ActiveMemory/ctx/internal/cli/task"
3738
"github.com/ActiveMemory/ctx/internal/cli/watch"
39+
"github.com/ActiveMemory/ctx/internal/config"
3840
)
3941

4042
// version is set at build time via ldflags
@@ -45,20 +47,59 @@ const version = "dev"
4547
// The root command provides the entry point for all ctx subcommands and
4648
// displays help information when invoked without arguments.
4749
//
50+
// Global flags:
51+
// - --context-dir: Override the context directory path (default: .context)
52+
// - --quiet: Suppress non-essential output
53+
// - --no-color: Disable colored output
54+
//
4855
// Returns:
4956
// - *cobra.Command: The configured root command with usage and version info
5057
func RootCmd() *cobra.Command {
51-
return &cobra.Command{
58+
var contextDir string
59+
var noColor bool
60+
61+
cmd := &cobra.Command{
5262
Use: "ctx",
5363
Short: "Context - persistent context for AI coding assistants",
5464
Long: `Context (ctx) maintains persistent context files that help
5565
AI coding assistants understand your project's architecture, conventions,
5666
decisions, and current tasks.
57-
67+
5868
Use 'ctx init' to create a .context/ directory in your project,
5969
then use 'ctx status', 'ctx load', and 'ctx agent' to work with context.`,
6070
Version: version,
71+
PersistentPreRun: func(cmd *cobra.Command, args []string) {
72+
// Apply global flag values
73+
if contextDir != "" {
74+
config.SetContextDir(contextDir)
75+
}
76+
if noColor {
77+
color.NoColor = true
78+
}
79+
},
6180
}
81+
82+
// Global flags available to all subcommands
83+
cmd.PersistentFlags().StringVar(
84+
&contextDir,
85+
"context-dir",
86+
"",
87+
"Override context directory path (default: .context)",
88+
)
89+
cmd.PersistentFlags().BoolVar(
90+
&config.Quiet,
91+
"quiet",
92+
false,
93+
"Suppress non-essential output",
94+
)
95+
cmd.PersistentFlags().BoolVar(
96+
&noColor,
97+
"no-color",
98+
false,
99+
"Disable colored output",
100+
)
101+
102+
return cmd
62103
}
63104

64105
// Initialize registers all ctx subcommands with the root command.

internal/cli/add/run.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ func WriteEntry(params EntryParams) error {
9595
return fmt.Errorf("unknown type %q", fType)
9696
}
9797

98-
filePath := filepath.Join(config.DirContext, fileName)
98+
filePath := filepath.Join(config.ContextDir(), fileName)
9999

100100
// Check if file exists
101101
if _, err := os.Stat(filePath); os.IsNotExist(err) {

internal/cli/compact/process.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func preCompactAutoSave(cmd *cobra.Command) error {
3333
green := color.New(color.FgGreen).SprintFunc()
3434

3535
// Ensure sessions directory exists
36-
sessionsDir := filepath.Join(config.DirContext, "sessions")
36+
sessionsDir := filepath.Join(config.ContextDir(), "sessions")
3737
if err := os.MkdirAll(sessionsDir, 0755); err != nil {
3838
return fmt.Errorf("failed to create sessions directory: %w", err)
3939
}
@@ -86,7 +86,7 @@ func buildPreCompactSession(timestamp time.Time) string {
8686
sb.WriteString("---\n\n")
8787

8888
// Read and include current TASKS.md content
89-
tasksPath := filepath.Join(config.DirContext, config.FilenameTask)
89+
tasksPath := filepath.Join(config.ContextDir(), config.FilenameTask)
9090
if tasksContent, err := os.ReadFile(tasksPath); err == nil {
9191
sb.WriteString("## Tasks (Before Compact)\n\n")
9292
sb.WriteString("```markdown\n")

internal/cli/compact/task.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ func compactTasks(
110110

111111
// Archive if requested
112112
if archive && len(archivableBlocks) > 0 {
113-
archiveDir := filepath.Join(config.DirContext, "archive")
113+
archiveDir := filepath.Join(config.ContextDir(), "archive")
114114
if err := os.MkdirAll(archiveDir, 0755); err == nil {
115115
archiveFile := filepath.Join(
116116
archiveDir,

internal/cli/complete/run.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import (
3535
func runComplete(cmd *cobra.Command, args []string) error {
3636
query := args[0]
3737

38-
filePath := filepath.Join(config.DirContext, config.FilenameTask)
38+
filePath := filepath.Join(config.ContextDir(), config.FilenameTask)
3939

4040
// Check if the file exists
4141
if _, err := os.Stat(filePath); os.IsNotExist(err) {

internal/cli/decisions/decisions.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ Examples:
6868

6969
// runReindex regenerates the DECISIONS.md index.
7070
func runReindex(cmd *cobra.Command, args []string) error {
71-
filePath := filepath.Join(config.DirContext, config.FilenameDecision)
71+
filePath := filepath.Join(config.ContextDir(), config.FilenameDecision)
7272

7373
// Check if file exists
7474
if _, err := os.Stat(filePath); os.IsNotExist(err) {

internal/cli/drift/fix.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ func fixStaleness(cmd *cobra.Command, ctx *context.Context) error {
152152
}
153153

154154
// Create an archive directory
155-
archiveDir := filepath.Join(config.DirContext, "archive")
155+
archiveDir := filepath.Join(config.ContextDir(), "archive")
156156
if err := os.MkdirAll(archiveDir, 0755); err != nil {
157157
return fmt.Errorf("failed to create archive directory: %w", err)
158158
}
@@ -209,10 +209,10 @@ func fixMissingFile(cmd *cobra.Command, filename string) error {
209209
return fmt.Errorf("no template available for %s: %w", filename, err)
210210
}
211211

212-
targetPath := filepath.Join(config.DirContext, filename)
212+
targetPath := filepath.Join(config.ContextDir(), filename)
213213

214214
// Ensure .context/ directory exists
215-
if err := os.MkdirAll(config.DirContext, 0755); err != nil {
215+
if err := os.MkdirAll(config.ContextDir(), 0755); err != nil {
216216
return fmt.Errorf("failed to create .context/: %w", err)
217217
}
218218

internal/cli/initialize/run.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func runInit(cmd *cobra.Command, force, minimal, merge bool) error {
3939
return err
4040
}
4141

42-
contextDir := config.DirContext
42+
contextDir := config.ContextDir()
4343

4444
// Check if .context/ already exists
4545
if _, err := os.Stat(contextDir); err == nil {

internal/cli/learnings/learnings.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ Examples:
6868

6969
// runReindex regenerates the LEARNINGS.md index.
7070
func runReindex(cmd *cobra.Command, args []string) error {
71-
filePath := filepath.Join(config.DirContext, config.FilenameLearning)
71+
filePath := filepath.Join(config.ContextDir(), config.FilenameLearning)
7272

7373
// Check if file exists
7474
if _, err := os.Stat(filePath); os.IsNotExist(err) {

0 commit comments

Comments
 (0)