File size: 3,857 Bytes
f14b4e9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use clap::{Parser, Subcommand};
use std::path::PathBuf;

use super::query::CliDirection;
use super::ui::OutputFormat;

/// Defines the top-level interface for the Firm CLI with clap.
#[derive(Parser, Debug)]
#[command(name = "firm")]
#[command(version, about = "Firm CLI: Work management in the terminal.")]
pub struct FirmCli {
    /// Path to firm workspace directory.
    #[arg(short, long, global = true, env = "FIRM_WORKSPACE")]
    pub workspace: Option<PathBuf>,

    /// Use cached firm graph?
    #[arg(short, long, global = true, env = "FIRM_CACHED")]
    pub cached: bool,

    /// Enable verbose output?
    #[arg(short, long, global = true, env = "FIRM_VERBOSE")]
    pub verbose: bool,

    /// Output format
    #[arg(short, long, global = true, default_value_t = OutputFormat::default(), env = "FIRM_FORMAT")]
    pub format: OutputFormat,

    #[command(subcommand)]
    pub command: FirmCliCommand,
}

/// Defines the available subcommands of the Firm CLI.
#[derive(Subcommand, Debug, PartialEq)]
pub enum FirmCliCommand {
    /// Initialize a new Firm workspace with default schemas and files.
    Init,
    /// Build workspace and entity graph.
    Build,
    /// Get an entity or schema.
    Get {
        /// Entity type (e.g. person, organization) or "schema"
        target_type: String,
        /// Entity ID (e.g. john_doe) or schema name (e.g. project)
        target_id: String,
    },
    /// List entities of a type, or list all schemas.
    List {
        /// Entity type (e.g. person, organization) or "schema" to list schemas
        target_type: String,
    },
    /// Gets entities related to a given entity.
    Related {
        /// Entity type (e.g. person)
        entity_type: String,
        /// Entity ID (e.g. john_doe)
        entity_id: String,
        /// Direction of relationships (incoming, outgoing, or both if not specified)
        #[arg(short, long)]
        direction: Option<CliDirection>,
    },
    /// Adds a new entity to a file in the workspace. If type, id or fields are not provided, this is done interactively.
    Add {
        /// Target firm file.
        to_file: Option<PathBuf>,
        /// Entity type for non-interactive mode (e.g., person, organization)
        #[arg(long)]
        r#type: Option<String>,
        /// Entity ID for non-interactive mode (e.g., john_doe)
        #[arg(long)]
        id: Option<String>,
        /// Field for non-interactive mode (can be repeated). Format: --field <field_name> <value>
        #[arg(long = "field", num_args = 2, value_names = ["FIELD_NAME", "VALUE"])]
        fields: Vec<String>,
        /// List declaration for non-interactive mode (can be repeated). Format: --list <field_name> <item_type>
        #[arg(long = "list", num_args = 2, value_names = ["FIELD_NAME", "ITEM_TYPE"])]
        lists: Vec<String>,
        /// List value for non-interactive mode (can be repeated). Format: --list-value <field_name> <value>
        #[arg(long = "list-value", num_args = 2, value_names = ["FIELD_NAME", "VALUE"])]
        list_values: Vec<String>,
    },
    /// Query entities in the workspace using a query language.
    Query {
        /// Query string (e.g., "from task | where is_completed == false | limit 5")
        query: String,
    },
    /// Find the source file for an entity or schema.
    Source {
        /// Entity type (e.g. person, organization) or "schema"
        target_type: String,
        /// Entity ID (e.g. john_doe) or schema name (e.g. project)
        target_id: String,
    },
    /// Check workspace files for errors. Optionally check a single file.
    Check {
        /// Path to a specific .firm file to check (checks entire workspace if omitted)
        file: Option<PathBuf>,
    },
    /// Start the language server (stdio transport).
    Lsp,
    /// Start the MCP server (stdio transport).
    Mcp,
}